概述
装饰模式主要用来动态的拓展现有的功能。主要包含四个角色,抽象构件 Component,具体构件 ConcreteComponent,抽象装饰类 Decorator,具体装饰类 ConcreteComponent。具体类图可参考类图小节。当需要给已有的具体构件拓展新功能时,增加具体装饰类即可,很灵活。
核心思想
有一个最基础的抽象构件 Component 类,ConcreteComponent 和 Decorator 都继承自 Component,并且 Decorator 聚合 Component。一般情况下,装饰者的构造器需要传入被装饰对象。
类图
从类图可知,ComponentA 和 Decorator 都继承自 Component,并且Decorator 聚合了 Component 类,那么理论上 Component 的子类都能用 Decorator 的子类来装饰,那么拓展新功能时,只需要拓展具体的 Decorator 就可以了,如 DecoratorC、DecoratorD 等等。
优缺点
- 优点
动态的给具体构件拓展新功能,解决了继承可能带来的类膨胀问题。 - 缺点
从使用上看,装饰类会一层一层的将被装饰类包起来,当出现问题时,刚好问题点在某个比较深的装饰类,那调试查找问题会比较麻烦。
代码实现
Component
public abstract class Component {
public abstract void hello();
}
ComponentA
public class ComponentA extends Component {
@Override
public void hello() {
System.out.println("ComponentA#hello()");
}
}
Decorator
public abstract class Decorator extends Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
}
DecoratorA
public class DecoratorA extends Decorator {
public DecoratorA(Component component) {
super(component);
}
@Override
public void hello() {
System.out.println("DecoratorA#hello()");
this.component.hello();
}
}
DecoratorB
public class DecoratorB extends Decorator {
public DecoratorB(Component component) {
super(component);
}
@Override
public void hello() {
System.out.println("DecoratorB#hello()");
this.component.hello();
}
}
TestDecorator
public class TestDecorator {
public static void main(String[] args) {
Component component = new ComponentA(); //待装饰对象
component = new DecoratorA(component); //使用 DecoratorA 对 component 进行装饰
component = new DecoratorB(component); //使用 DecoratorB 对 component 进行装饰
component.hello();
}
}
运行 TestDecorator 的 main 方法,输出如下,
DecoratorB#hello()
DecoratorA#hello()
ComponentA#hello()
哪里见过这种模式?
在 JDK 中,java.io.Reader,java.io.InputStreamReader,java.io.BufferedReader, 这三个类及它们子类的实现上使用了装饰模式,其类图如下,
这个类图是不是很眼熟,没错,这就是上面的装饰模式的实现类图。可以看到 Reader 是一个最基础的类,InputStreamReader 在这里为被装饰者,BufferedReader 是装饰者。BufferedReader 构造时需要传入 Reader 对象,构造方法实现如下,
即 BufferedReader 聚合了 Reader 对象。
总结
装饰模式主要用来给对象动态拓展功能,在项目开发过程中非常灵活,当需要增加或删除某个功能时,只需要加上或去掉对应的装饰类即可,从装饰模式的类图可以一目了然整体的模式设计。
在 JDK 中也有很多地方用到装饰模式,例如 java.io.Reader 的实现。
下面是公众号,欢迎扫描二维码,感谢关注和支持!
公众号名称:ToSimple