一、是什么?
在类原有功能的基础上扩展功能。比如字节流转字符流,字符流就相当于是装饰器,在字节流原有的基础之上扩展功能。
二、类图
三、代码实现
public abstract class Component {
abstract void method();
}
public class ConcreteComponent extends Component{
@Override
public void method() {
System.out.println("ConcreteComponent method...");
}
}
public abstract class ComponentDecorator extends Component {
Component component;
public ComponentDecorator(Component component) {
this.component = component;
}
}
public class ConcreteComponentDecorator extends ComponentDecorator{
public ConcreteComponentDecorator(Component component) {
super(component);
}
@Override
void method() {
System.out.println("ConcreteComponentDecorator method ....");
this.component.method();
}
void myMethod() {
System.out.println("ConcreteComponentDecorator myMethod....");
}
public static void main(String[] args) {
ConcreteComponent concreteComponent = new ConcreteComponent();
ConcreteComponentDecorator concreteComponentDecorator = new ConcreteComponentDecorator(concreteComponent);
concreteComponentDecorator.method();
}
}
四、与代理模式的区别(似我非我,本质不同)
代理模式: 相当于外卖小哥代客户买肯德基,但外卖小哥并不是客户,只是委托另一个角色去完成你不想干的事。从代码中举例,Spring事务控制,代理模式把开启、关闭、提交、回滚等非业务操作交给代理类去做,但这个代理类不能当成真正的业务类,真正吃肯德基的核心业务还是要被代理的类来做。
装饰器模式: 相当于外卖小哥给自己点了份肯德基,他本身就是客户,做跑腿的事,也做吃肯德基的事。从代码中举例,字节流转字符流,字符流转缓冲字符流,再怎么转它还是流。
他们的区别也类似,客户与律师事务所,让律师代替自己打官司 ,和客户把自己装饰成律师,自己给自己打官司,是律师也是客户。
五、优缺点
优点:
- 动态扩展功能,即插即用,比继承灵活。
- 完全遵守开闭原则
- 可以多个装饰器组合使用,比如字节流转字符流,字符流转缓冲字符流
缺点:
- 会增加许多子类,过度使用会增加程序得复杂性