Skip to content

装饰模式(Decorator Pattern)

装饰器模式(Decorator Pattern))允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

何时使用:在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

关键代码

  1. Component 类充当抽象角色,不应该具体实现。
  2. 修饰类引用和继承 Component 类,具体扩展类重写父类方法。

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:多层装饰比较复杂。

使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。

注意事项:可代替继承。

装饰模式之透明模式

  • 要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型。

  • 对于客户端而言,具体构件对象和具体装饰对象没有任何区别

  • 可以让客户端透明地使用装饰之前的对象和装饰之后的对象,无须关心它们的区别

  • 可以对一个已装饰过的对象进行多次装饰,得到更为复杂、功能更为强大的对象

java
Component component_o,component_d1,component_d2; //全部使用抽象构件定义
component_o = new ConcreteComponent();
component_d1 = new ConcreteDecorator1(component_o);
component_d2 = new ConcreteDecorator2(component_d1);
component_d2.operation();
//无法单独调用component_d2的addedBehavior()方法

装饰模式之半透明模式

  • 用具体装饰类型来定义装饰之后的对象,而具体构件使用抽象构件类型来定义

  • 对于客户端而言,具体构件类型无须关心,是透明的;但是具体装饰类型必须指定,这是不透明的

  • 可以给系统带来更多的灵活性,设计相对简单,使用起来也非常方便

  • 客户端使用具体装饰类型来定义装饰后的对象,因此可以单独调用addedBehavior()方法

  • 最大的缺点在于不能实现对同一个对象的多次装饰,而且客户端需要有区别地对待装饰之前的对象和装饰之后的对象

    java
    Component component_o; //使用抽象构件类型定义
    component_o = new ConcreteComponent();
    component_o.operation();
    ConcreteDecorator component_d; //使用具体装饰类型定义
    component_d = new ConcreteDecorator(component_o);
    component_d.operation();
    component_d.addedBehavior(); //单独调用新增业务方法
### 实现

#### 1. 创建一个接口:

- shape.java
```java
public interface Shape {
   void draw();
}

2. 创建实现接口的实体类

  • Rectangle.java

    java
    public class Rectangle implements Shape {
    
     @Override
     public void draw() {
        System.out.println("Shape: Rectangle");
     }
    }
  • Circle.java

    java
    public class Circle implements Shape {
    
     @Override
     public void draw() {
        System.out.println("Shape: Circle");
     }
    }

3. 创建实现了 Shape 接口的抽象装饰类

  • ShapeFactory.java

    java
    public abstract class ShapeDecorator implements Shape {
     protected Shape decoratedShape;
    
     public ShapeDecorator(Shape decoratedShape){
        this.decoratedShape = decoratedShape;
     }
    
     public void draw(){
        decoratedShape.draw();
     }  
    }

4. 创建扩展了 ShapeDecorator 类的实体装饰类

  • RedShapeDecorator.java
java
public class RedShapeDecorator extends ShapeDecorator {

   public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);     
   }

   @Override
   public void draw() {
      decoratedShape.draw();         
      setRedBorder(decoratedShape);
   }

   private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
   }
}

5. 使用 RedShapeDecorator 来装饰 Shape 对象

DecoratorPatternDemo.java

java
public class DecoratorPatternDemo {
   public static void main(String[] args) {

      Shape circle = new Circle();
      ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
      ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
      //Shape redCircle = new RedShapeDecorator(new Circle());
      //Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println("Circle with normal border");
      circle.draw();

      System.out.println("\nCircle of red border");
      redCircle.draw();

      System.out.println("\nRectangle of red border");
      redRectangle.draw();
   }
}

6. 执行程序,输出结果

java
Circle with normal border
Shape: Circle

Circle of red border
Shape: Circle
Border Color: Red

Rectangle of red border
Shape: Rectangle
Border Color: Red

实现2

情景模拟

我们还是拿汽车来举例子吧。 现在的汽车越来越智能化了,什么定速巡航、自动刹车、车道偏离等功能都逐渐进入我们的生活,为我们带来了更为便利的出行。

假设上述提到的定速巡航、自动刹车、车道偏离三个功能就是我们想要为汽车装饰的功能,汽车默认的功能配置有:基本配置。

得到具体的汽车(宝马、奥迪、奔驰)后,我们可以选择性地增加装饰功能。

代码实现

cpp
class Car
{
public:
    virtual void show() = 0;
};

// 三个实体的汽车类
class Bmw :public Car
{
public:
    void show()
    {
        cout << "这是一辆宝马汽车,配置有:基本配置";
    }
};
class Audi :public Car
{
public:
    void show()
    {
        cout << "这是一辆奥迪汽车,配置有:基本配置";
    }
};
class Benz :public Car
{
public:
    void show()
    {
        cout << "这是一辆奔驰汽车,配置有:基本配置";
    }
};

// 装饰器1 定速巡航
class Decorator01 :public Car
{
public:
    Decorator01(Car* p) :pCar(p) {}
    void show()
    {
        pCar->show();
        cout << ",定速巡航";
    }
private:
    Car* pCar;
};
// 装饰器2 自动刹车
class Decorator02 :public Car
{
public:
    Decorator02(Car* p) :pCar(p) {}
    void show()
    {
        pCar->show();
        cout << ",自动刹车";
    }
private:
    Car* pCar;
};
// 装饰器3 定速巡航
class Decorator03 :public Car
{
public:
    Decorator03(Car* p) :pCar(p) {}
    void show()
    {
        pCar->show();
        cout << ",车道偏离";
    }
private:
    Car* pCar;
};

int main()
{
    Car* p1 = new Decorator01(new Bmw());
    p1 = new Decorator02(p1);
    p1 = new Decorator03(p1);
    p1->show();
    cout << endl;

    Car* p2 = new Decorator02(new Audi());
    p2->show();
    cout << endl;

    Car* p3 = new Decorator03(new Benz());
    p3->show();
    cout << endl;

    return 0;
}

运行结果

可以看到,我们在运行代码中: 给宝马汽车增加了Decorator01(定速巡航)、Decorator02(自动刹车)、Decorator03(车道偏离)的配置; 给奥迪汽车增加了Decorator02(自动刹车)配置; 给奔驰汽车增加了Decorator03(车道偏离)配置。