定义
动态地给一个对象添加一些额外的功能,就增加功能来说,装饰者模式比生成子类更为灵活。
如我们生活中的早餐煎饼,可以加鸡蛋,加香肠,加蔬菜,可以很灵活的组合。
结构
- Component,抽象组件,定义为一个接口来规范被装饰的对象。
- ConcreteComponent,具体的组件对象,实现组件接口,通常就作为被装饰的对象。
- Decorator,抽象装饰者,所有装饰者的父类,内部持有一个被装饰的对象。
- ConcreteDecorator,具体的装饰者对象,负责实现增强被装饰对象的功能。
简单实现
抽象组件
public interface Component {
void operation();
}
具体组件
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("ConcreteComponent operation()");
}
}
抽象装饰者
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
}
具体装饰者
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
@Override
public void operation() {
component.operation();
System.out.println("ConcreteDecorator operation()");
}
}
另一个装饰者
public class ConcreteDecorator2 extends Decorator {
public ConcreteDecorator2(Component component) {
super(component);
}
@Override
public void operation() {
component.operation();
System.out.println("ConcreteDecorator2 operation()");
}
}
客户端
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
//装饰
Component decorator = new ConcreteDecorator(component);
//再装饰一次
Component decorator2 = new ConcreteDecorator2(decorator);
decorator2.operation();
}
}
输出结果为
ConcreteComponent operation()
ConcreteDecorator operation()
ConcreteDecorator2 operation()
装饰者模式在JDK和Spring中的实现
JDK中的实现
JDK中的IO流
InputStream类似于装饰者模式中的Component抽象组件接口,
ByteArrayInputStream类似于ConcreteComponent具体组件,
FilterInputStream类似于Decorator抽象装饰者,
BufferedInputStream类似于ConcreteDecorator具体装饰者。
Spring中的实现
Spring中的TransactionAwareCacheDecorator,从名称就可以看出使用了装饰者模式
总结
优点
- 相比继承更加的灵活,在不改变原有对象的情况下,动态地给一个对象扩展功能。
- 通过多次装饰,可以组合出功能更加强大的对象。
缺点
- 会产生很多装饰类,增加了系统复杂度。
本质
装饰者模式的本质是动态组合,动态是手段,组合是目的。通过对象组合来实现为被装饰对象增加功能的目的。
使用场景
- 在不影响其他对象的情况下,动态、透明的给对象增强功能。
- 当不能使用继承的方式来扩展功能时。
和代理模式的区别
装饰者模式(左边)和代理模式(右边)在结构上很相似,但两种模式面向的功能扩展面是不同的。
- 装饰者模式本质为动态组合,强调自身功能的扩展
- 代理模式本质为控制对象访问,强调对过程的控制
以小明想租房为例,以装饰者模式来思考就是小明自己要增加查找房源、联系房东等功能扩展,以代理模式来思考就是小明直接找中介,让中介查找房源、联系房东。
参考
大战设计模式【3】—— 装饰模式
大战设计模式(第二季)【4】———— 从源码看装饰者模式
设计模式——装饰者模式
设计模式(九)——装饰者模式(io源码分析)
设计模式的征途—10.装饰(Decorator)模式
装饰器模式(装饰设计模式)详解
研磨设计模式-书籍