带你了解不一样的装饰器模式

270 阅读4分钟

这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战

装饰器模式

概念

装饰器模式(Decorator Pattern),也称为包装模式(Wrapper Pattern),是指允许向一个现有的对象添加新的功能,同时又不改变其结构。或者说在不改变原有对象的基础上,将功能附加到原有对象上,提供了比继承更有弹性的替代方案,根据类的创建过程,装饰器模式属于结构型模式。

装饰器模式的主要核心就是功能扩展,可以透明并且动态的扩展对象类的功能。

装饰器应用场景

  • SpringSession中如何进行session与redis关联?

  • MyBatisPlus提取了QueryWrapper,这是什么?

  • Spring中的BeanWrapper是做什么?包装了Bean。bean的功能增强?

  • SpringWebflux中的WebHandlerDecorator?

  • 已存的类,每一天在某个功能使用的时候发现不够,就可以装饰器。

装饰器模式的基本用法

装饰器模式一般情况下有四类角色

  • 抽象构件(Component)角色:可以是一个类或者一个接口类,该类充当被装饰类的原始对象,规定了被装饰类对象的行为。

  • 具体构件(ConcreteComponent)角色:实现或者继承抽象构件(Component)角色的的一个具体对象,即被装饰对象,通过装饰角色为其添加一些职责。

  • 抽象装饰(Decorator)角色:通用的装饰ConcreteComponent的装饰器,其内部必然是有一个属性指向抽象构件,一般实现就是一个抽象类。并包含具体构件的实例,可以通过其子类扩展具体构件的功能。

  • 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任,理论上每个ConcreteDecorator都扩展了Component对象的一个功能。

下面是装饰器模式的通用写法。

  • Shape(抽象构件角色)
public interface Shape {
    void draw();
}

创建一个画图Shape类

  • Circle(具体构件角色)
public class Circle  implements Shape{
    @Override
    public void draw() {
        System.out.println("Shape: Circle");
    }
}

创建画圆形的类

  • Rectangle(具体构件角色)
public class Rectangle implements Shape{
    @Override
    public void draw() {
        System.out.println("Shape: Rectangle");
    }
}

创建长方形Rectangle类

  • ShapeDecorator(抽象装饰角色)
public abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;
    public ShapeDecorator(Shape decoratedShape) {
        this.decoratedShape = decoratedShape;
    }
    @Override
    public void draw() {
        decoratedShape.draw();
    }
}

创建抽象装饰器画图ShapeDecorator类,里面定义有参构造方法和重写了draw画图方法。

  • RedShapeDecorator(具体装饰角色)
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类,该类继承了ShapeDecorator装饰器,然后重写了属于自己的draw方法并新建属于自己的setRedBorder方法设置了特定的边框颜色。

  • UML结构图

image.png

通过上述代码和uml结构,通过一层一层的嵌套而不一直继承来实现各自的方法。

装饰器模式的优点和缺点

优点

  • 装饰器模式是继承的有力补充,但是装饰器模式比继承灵活,他在不改变原有对象的情况下动态地给一个对象新增了扩展的功能。

  • 装饰器模式通过使用不同的装饰及这些装饰类的排列组合,可以实现不同效果和不同的功能。

  • 装饰器模式完全遵守开闭原则。即对新增开放,对修改关闭。

缺点

  • 装饰器模式使用过多会导致增加许多子类,过度使用会增加程序的复杂性。

  • 装饰器模式在进行动态装饰时,多层装饰会使代码更加复杂,导致可读性降低

装饰器模式和代理模式的区别

  • 相同点

装饰器模式和代理模式从设计模式的分类看都属于结构型模式,因为装饰器和代码模式都是用来组合的关系,然后两者都通过对自身对象的方法进行增强,达到自己想要的效果。

  • 不同点

    • 装饰器模式是一种特殊的代理模式

    • 代理模式主要是注重于代理过程的控制,即注重对与对象某一功能的流程控制,代理模式可以控制对象做一些事情,只要核心在于借助对象完成某一流程,而非使用对象的功能。

    • 装饰器模式强调时对于自身的功能扩展,不关心外界如何调用自己,只注重于自己的动态扩展和增强,但是装饰器模式对于装饰前还是装饰后都还是对象本身。