是你还有你,一切拜托你。 是你——继承,还有你——关联,拜托你——调用父类方法
继承是为了后续的继续装饰,如果不继承,后续的加强将不能传递他们共有的父类作为参数,而是他们的实现类,耦合度太高。
意图(Intent)
动态地给一个对象增加一些额外的职责。就增加功能而言,装饰模式相比生成子类更加灵活。
结构(Structure)
-
Component 抽象构件
-
ConcreteComponent 具体构件
-
Decorator 装饰角色
-
ConcreteDecorator 具体装饰角色
装饰模式的几个要点
-
通过采用组合、而非继承的手法,装饰模式实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多姿类衍生问题”。
-
Component类在装饰模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明——换言之,Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。
-
Decorator类在接口上表现为 is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但是实现上又表现为 has-a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或者多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。
-
Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决”主体类在多个方向上的扩展功能“——是为“装饰”的含义。
使用场景
-
需要扩展一个类的功能,或给一个类添加附加功能
-
需要动态地给一个对象增加功能,这些功能可以在动态地撤销。
-
需要为一批的兄弟类进行改装或加功能,首选装饰模式。
实例代码
抽象构件:
public abstract class Component {
public abstract void operate();
}
具体构件:
public class ConcreteComponent extends Component {
@Override
public void operate() {
System.out.println("do something!");
}
}
抽象装饰者:
public abstract Decorator extends Component {
private Component component = null;
//通过构造函数传递被修饰者
public Decorator(Cpmponent component){
this.component = component;
}
//委托给被修饰者执行
@Override
public void operate(){
this.component.operate();
}
}
具体装饰类:
public class ConcreteDecorator extends Decorator {
//传入被修饰者
public ConcreteDecorator(Component component){
super(component);
}
//被装饰方法之前调用
public void before(){
System.out.println("operate之前调用!");
}
//被装饰方法之后调用
public void later(){
System.out.println("operate之后调用!");
}
//重写父类的operate方法
public void operate(){
this.before();
super.operate();
this.later();
}
}
场景类:
public class Clent{
public static void main(Stirng[] args) {
Component component = new ConcreteComponent();
//第一次装饰
component = new ConcreteDecorator(component);
//可被多个装饰类装饰
......
//修饰后运行
component.operator();
}
}