装饰器模式:Decorator Pattern,也叫作包装器模式(Wrapper Pattern),指在不改变原有对象的基础上,动态地给一个对象添加一些额外的职责
应用场景:
- 用于扩展一个类的功能,或者给一个类添加附加职责
- 动态地给一个对象添加功能,这些功能支持再被动态地撤销
- 需要为一批平行的兄弟类进行改装或加装功能
装饰器与代理模式的区别:
- 装饰器:强调自身的功能的扩展
- 代理模式:强调对代理过程的控制
典型应用:
- java 的 IO 流设计
- Spring 的 TransactionAwareCacheDecorator 类
实现原理:
- 让装饰器实现与被装饰类相同的接口,使得装饰器与被扩展类类型一致,并在构造函数中传入该接口对象,然后在实现这个接口的被包装类对象的现有功能上添加新功能
- 由于装饰器与被包装类属于同一类型(实现相同接口),且构造函数的参数为其接口实现类,因此,装饰器模式具备嵌套调用,这样就能使用装饰器模式一层一层地对底层被包装类进行功能扩展
UML 图:
装饰器模式的 4 个角色:
- 抽象组件:Component,可以是一个接口或抽象类,充当被装饰类的原始对象,规定了被装饰对象的行为
- 具体组件:ConcreteComponent,实现了Component的一个具体对象,即被装饰对象
- 抽象装饰器:Decorator,通用的装饰 ConcreteComponent 的装饰器,其内部必然有一个属性指向Component;其实现一般是一个抽象类,主要为了让其子类按照其构造形式传入一个Component,这是强制的通用行为。如果系统中装饰逻辑单一,则并不需要实现许多装饰器,可以直接省略该类,而直接实现一个具体装饰器即可
- 具体装饰器:ConcreteDecorator,Decorator的具体实现类,理论上,每个ConcreteDecorator都扩展了Component对象的一种功能
public class DecoratorDemo {
public static void main(String[] args) {
// 首先创建需要被装饰的原始对象,即被装饰的对象
Component component = new ConcreteComponent();
// 给被装饰的对象增加功能1并调用相关方法
Decorator decorator = new ConcreteDecorator1(component);
decorator.operation();
// 给被装饰的对象增加功能2并调用相关方法
Decorator decorator1 = new ConcreteDecorator2(component);
decorator1.operation();
// 在装饰器1上使用装饰器2
Decorator decorator2 = new ConcreteDecorator2(decorator);
decorator2.operation();
}
interface Component {
void operation();
}
static class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("被装饰的目标方法!");
}
}
abstract static class Decorator implements Component{
// 持有对象组件
protected Component component;
// 构造方法,传入组建对象
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
static class ConcreteDecorator1 extends Decorator {
public ConcreteDecorator1(Component component) {
super(component);
}
@Override
public void operation() {
System.out.println("装饰1增强!");
super.operation();
System.out.println("装饰器1增强!");
}
}
static class ConcreteDecorator2 extends Decorator {
public ConcreteDecorator2(Component component) {
super(component);
}
@Override
public void operation() {
System.out.println("装饰2增强!");
super.operation();
System.out.println("装饰器2增强!");
}
}
}