装饰模式 - Decorator Pattern
WHAT
定义
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
类图
Component抽象构件
Component是一个接口或者是抽象类,定义我们最核心的对象,也就是最原始的对象。
装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构建
public abstract class Component {
// 抽象的方法
public abstract void operate();
}
ConcreteComponent 具体构件
最核心、最原始、最基本的接口或抽象类的实现,需要装饰的对象。
public class ConcreteComponent extends Component{
// 具体实现
@Override
public void operate(){
System.out.println("do Something");
}
}
Decorator装饰角色
一般是一个抽象类,用来实现接口或者抽象方法,里面不一定有抽象的方式,但必然有一个private变量啊指向Component抽象构件。
public abstract class Decorator extends Component {
private Component component = null;
// 通过构造函数传递被修饰者
public Decorator(Component _component){
this.component = _component;
}
// 委托给被修饰者执行
@Override
public void operate(){
this.component.operate();
}
}
具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,把最核心的、最原始的、最基本的东西装饰成其他东西,可以将原来的对象装饰成合适的新对象。
public class ConcreteDecorator1 extends Decorator {
// 定义被修饰者
public ConcreteDecorator1(Component _component){
super(_component);
}
// 定义自己的修饰方法
private void method1(){
System.out.println("method1 修饰");
}
// 重写父类的Operation方法
public void operate(){
this.method1();
super.operate();
}
}
public class ConcreteDecorator2 extends Decorator {
// 定义被修饰者
public ConcreteDecorator2(Component _component){
super(_component);
}
// 定义自己的修饰方法
private void method2(){
System.out.println("method2 修饰");
}
// 重写父类的Operation方法
public void operate(){
this.method2();
super.operate();
}
}
上层模块
模拟高层模块的耦合关系
public class Client {
public static void main(String[] args){
Component component = new ConcreteComponent();
// 第一次修饰
component = new ConcreteDecorator1(component);
// 第二次修饰
component = new ConcreteDecorator2(component);
// 修饰后运行
component.operate();
}
}
WHY
优势
- 装饰类和被装饰类可以独立发展,而不会相互耦合
- Component类无须知道Decorator类
- Decorator类是从外部来扩展Component类的功能
- Decorator不用知道具体的构件
- 装饰模式是继承关系的一个替代方案
- 无论装饰多少层,返回的对象还是Component
- 装饰模式可以动态地扩展一个实现类的功能, 扩展性非常好
- 通过装饰模式重新封装一个类
缺点
- 多层的装饰比较复杂
- 需要剥到最后才发现里面的装饰出现了问题,增加了复杂度
HOW
使用场景
- 需要扩展一个类的功能,或给一个类增加附加功能
- 需要动态地给一个对象增加功能,这些工鞥呢可以再动态撤销
- 需要为一批的兄弟类进行改装或加装功能
最佳实践
- 装饰模式是对继承的有力补充。
- 装饰类可以替代继承,解决我们类的膨胀的问题。
- 继承是静态地给类增加功能,而装饰模式则是动态地增加功能。
TIPS
-
原始方法和装饰方法的执行顺序在具体的装饰类是固定的,可以通过方法重载实行多种执行顺序。
-
尽量装饰类的数量,以便降低系统的复杂度。
《设计模式之禅》第十七章 装饰模式