装饰模式 - 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

  • 原始方法和装饰方法的执行顺序在具体的装饰类是固定的,可以通过方法重载实行多种执行顺序。

  • 尽量装饰类的数量,以便降低系统的复杂度。


《设计模式之禅》第十七章 装饰模式