装饰模式

软件设计模式
2021-05-17 14:29 · 阅读时长4分钟
小课

装饰模式主要用来动态扩展原来类的功能。对于面向对象编程,我们可以通过继承来扩展类的功能,但是有几种情况使用继承的方式却不一定好实现,比如说

  • 原来的类使用final修饰,无法通过继承扩展。
  • 需要动态扩展,对已经实例化之后的类进行扩展。
  • 功能组合扩展,多个扩展功能想要组合使用。

装饰模式和代理模式以及适配器模式在结构上很相似,但是它们的适用场景,或者说使用目的是有区别的,下面通过一个示例来看看装饰模式的简单用法。假设原本有一个接口Shape和一个实现类Rectangle用于画矩形。

public interface Shape {
    void draw();
}

public class RectangleImpl implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个矩形");
    }
}

现在我们想在原来的矩形上加一个边框、内阴影、外阴影,我们可以先创建一个装饰类的基类BaseDecorator

public abstract class BaseDecorator implements Shape {

    protected final Shape shape;

    public BaseDecorator(Shape shape) {
        this.shape = shape;
    }
}

然后分别实现几个装饰类,BorderDecoratorInnerShadowDecoratorOuterShadowDecorator

1public class BorderDecorator extends BaseDecorator {
2    public BorderDecorator(Shape shape) {
3        super(shape);
4    }
5    @Override
6    public void draw() {
7        System.out.println("画边框");
8        shape.draw();
9    }
10}
11
12public class InnerShadowDecorator extends BaseDecorator {
13    public InnerShadowDecorator(Shape shape) {
14        super(shape);
15    }
16    @Override
17    public void draw() {
18        System.out.println("画内阴影");
19        shape.draw();
20    }
21}
22
23public class OuterShadowDecorator extends BaseDecorator {
24    public OuterShadowDecorator(Shape shape) {
25        super(shape);
26    }
27    @Override
28    public void draw() {
29        System.out.println("画外阴影");
30        shape.draw();
31    }
32}

使用的时候可以根据需求进行组合,比如说要画一个带外阴影和边框的矩形,只需要一层层包装即可。

Shape origin = new Rectangle();
Shape outerShadow = new OuterShadowDecorator(origin);
Shape rectangle = new BorderDecorator(outerShadow);
总结

使用装饰模式可以实现动态、组合扩展功能,但是如果装饰类太多,使用起来也非常麻烦,而且在实际开发中可能还需要考虑多个装饰类的顺序问题。

装饰者模式设计模式decorator