0%

【设计模式】Decorator Pattern 装饰器模式

装饰器模式理解剖析以及应用

装饰器模式

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

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

意图

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

解决问题

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

何时使用?

  1. 在不想增加很多子类的情况下扩展类。
  2. 扩展一个类的功能。
  3. 动态增加功能,动态撤销。

应用环境举例

  1. 孙悟空有 72 变,当他变成”庙宇”后,他的根本还是一只猴子,但是他又有了庙宇的功能。
  2. 不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。

优点

  1. 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
  2. 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
  3. 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  4. 装饰器模式完全遵守开闭原则

缺点

  1. 多层装饰比较复杂。
  2. 装饰器模式会增加许多子类?,过度使用会增加程序得复杂性。

类图

  • 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  • 具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  • 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  • 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

实现

  • 抽象构件角色

    1
    2
    3
    interface Component {
    public void operation();
    }
  • 具体构件角色

    1
    2
    3
    4
    5
    6
    7
    8
    class ConcreteComponent implements Component {
    public ConcreteComponent() {
    System.out.println("创建具体构件角色");
    }
    public void operation() {
    System.out.println("调用具体构件角色的方法operation()");
    }
    }
  • 抽象装饰角色

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
    this.component = component;
    }

    public void operation() {
    component.operation();
    }
    }

  • 具体装饰角色

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
    super(component);
    }

    public void operation() {
    super.operation();
    addedFunction();
    }

    public void addedFunction() {
    System.out.println("为具体构件角色增加额外的功能addedFunction()");
    }
    }
  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class DecoratorPattern {
    public static void main(String[] args) {
    Component p = new ConcreteComponent();
    p.operation();
    System.out.println("---------------------------------");
    Component d = new ConcreteDecorator(p);
    d.operation();
    }
    }

    结果

    1
    2
    3
    4
    5
    创建具体构件角色
    调用具体构件角色的方法operation()
    ---------------------------------
    调用具体构件角色的方法operation()
    为具体构件角色增加额外的功能addedFunction()

实例

我们将创建一个 Shape 接口和实现了 Shape 接口的实体类。 然后我们创建一个实现了 Shape 接口的抽象装饰类 ShapeDecorator,并把 Shape 对象作为它的实例变量。 RedShapeDecorator 是实现了 ShapeDecorator 的实体类。 DecoratorPatternDemo 类使用 RedShapeDecorator 来装饰 Shape 对象。 * 创建一个接口: Shape.java
1
2
3
public interface Shape {
void draw();
}
* 创建实现接口的实体类。 Rectangle.java
1
2
3
4
5
6
7
public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
Circle.java
1
2
3
4
5
6
7
public class Circle implements Shape {

@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
  • 创建实现了 Shape 接口的抽象装饰类。
    ShapeDecorator.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

    public ShapeDecorator(Shape decoratedShape){
    this.decoratedShape = decoratedShape;
    }

    public void draw(){
    decoratedShape.draw();
    }
    }
  • 创建扩展了 ShapeDecorator 类的实体装饰类。
    RedShapeDecorator.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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");
    }
    }
  • 使用 RedShapeDecorator 来装饰 Shape 对象。
    DecoratorPatternDemo.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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();
    }
    }

    结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Circle with normal border
    Shape: Circle

    Circle of red border
    Shape: Circle
    Border Color: Red

    Rectangle of red border
    Shape: Rectangle
    Border Color: Red

感谢查阅