侧边栏壁纸
博主头像
赫兹

谁辜负过自己,说不上可惜

  • 累计撰写 18 篇文章
  • 累计创建 13 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

装饰器模式

赫兹
2022-10-11 / 0 评论 / 0 点赞 / 327 阅读 / 1,828 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-10-11,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

装饰器模式

介绍

装饰设计模式允许我们动态地向对象添加功能和行为,而不会影响同一类中其他现有对象的行为。
我们使用继承来扩展类的行为。这在编译时发生,该类的所有实例都会获得扩展行为。
装饰器设计模式允许我们在运行时向对象(而不是类)添加功能,我们可以根据自己的需求和选择将此自定义功能应用于单个对象。

  • 装饰器模式允许用户向现有对象添加新功能,而不改变其结构。因此,原始类没有变化。

  • 装饰器设计模式是一种结构模式,它为现有类提供包装。

  • 装饰器设计模式使用抽象类或具有组合的接口来实现包装器。

  • 装饰器设计模式创建装饰器类,它包装原始类,并通过保持类方法的签名不变来提供附加功能。

  • 装饰设计模式最常用于应用单一责任原则,因为我们将功能划分为具有独特关注区域的类。

  • 装饰设计模式在结构上类似于责任链模式。

实现

让我们看一个例子来更好地理解这个模式。

假设我们有一个Shape接口

public interface Shape {
    void draw();
    void resize();
    String description();
    boolean isHide();
}

现在,我们有两个Shape的具体实现类CircleRectangle,来定义特定的形状。

下面是Circle代码示例:

public class Circle implements Shape {

    @Override
    public void draw() {
        System.out.println("画个圈圈");
    }

    @Override
    public void resize() {
        System.out.println("调整圆圈的大小");
    }

    @Override
    public String description() {
        return "圆形";
    }

    @Override
    public boolean isHide() {
        return false;
    }

}

下面是Rectangle代码示例:

public class Rectangle implements Shape {

    @Override
    public void draw() {
        System.out.println("画个长方形");
    }

    @Override
    public void resize() {
        System.out.println("调整长方形大小");
    }

    @Override
    public String description() {
        return "长方形";
    }

    @Override
    public boolean isHide() {
        return false;
    }

}

​ 现在,我们已经可以绘制CircleRectangle。但是,我们希望为Shape提供一些附加功能,如填充颜色、线颜色、线厚度、线样式等。
​ 首先,我们将创建一个实现Shape的抽象包装器(decorator)类。我将在这个示例中使用ShapeDecorator

public abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

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

}

​ 我让ShapeDecorator类是抽象类,是为了避免直接被实例化,因为这只是一个包装器,没有向Shape中添加任何功能。此外,我还实现了Shape,为了给Shape的实现类(CircleRectanagle)添加其他功能。

ShapeColorLineStyle创建枚举。下面是Color的枚举:

public enum Color {
    /**
     * 颜色形状枚举
     */
    RED,
    GREEN,
    BLUE,
    YELLOW,
    WHITE,
    BLACK,
    ORANGE,
    MAROON
}

下面是LineStyle的枚举:

public enum LineStyle {
    /**
     * 线条样式枚举
     */
    SOLID,
    DASH,
    DOT,
    DOUBLE_DASH,
    DASH_SPACE
}

创建FillColorDecorator以在形状中添加填充颜色的功能。

public class FillColorDecorator extends ShapeDecorator {

    protected Color color;

    public FillColorDecorator(Shape decoratedShape, Color color) {
        super(decoratedShape);
        this.color = color;
    }

    @Override
    public void draw() {
        decoratedShape.draw();
        System.out.println("填充的颜色是: " + color);
    }

    /**
     * 功能无变化
     * 如果愿意,我们可以添加功能。没有限制
     * 但需要我们维护Shape API的结构
     */
    @Override
    public void resize() {
        decoratedShape.resize();
    }

    @Override
    public String description() {
        return decoratedShape.description() + " filled with " + color + " color.";
    }

    /**
     * 功能无变化
     */
    @Override
    public boolean isHide() {
        return decoratedShape.isHide();
    }

}

创建LineColorDecorator以在形状中添加线条颜色的功能。

public class LineColorDecorator extends ShapeDecorator {

    protected Color color;

    public LineColorDecorator(Shape decoratedShape, Color color) {
        super(decoratedShape);
        this.color = color;
    }

    @Override
    public void draw() {
        decoratedShape.draw();
        System.out.println("线条颜色是: " + color);
    }

    /**
     * 功能无变化
     */
    @Override
    public void resize() {
        decoratedShape.resize();
    }

    @Override
    public String description() {
        return decoratedShape.description() + " drawn with " + color + " color.";
    }

    /**
     * 功能无变化
     */
    @Override
    public boolean isHide() {
        return decoratedShape.isHide();
    }

}

创建LineThicknessDecorator以在形状中添加自定义线宽的功能。

public class LineThinknessDecorator extends ShapeDecorator {

    protected double thickness;

    public LineThinknessDecorator(Shape decoratedShape, double thickness) {
        super(decoratedShape);
        this.thickness = thickness;
    }

    @Override
    public void draw() {
        decoratedShape.draw();
        System.out.println("线条宽度是: " + thickness);
    }

    /**
     * 功能无变化
     */
    @Override
    public void resize() {
        decoratedShape.resize();
    }

    @Override
    public String description() {
        return decoratedShape.description() + " drawn with line thickness " + thickness + ".";
    }

    /**
     * 功能无变化
     */
    @Override
    public boolean isHide() {
        return decoratedShape.isHide();
    }

}

创建LineStyleDecorator以在形状中添加自定义线样式的功能

public class LineStyleDecorator extends ShapeDecorator {

    protected LineStyle style;

    public LineStyleDecorator(Shape decoratedShape, LineStyle style) {
        super(decoratedShape);
        this.style = style;
    }

    @Override
    public void draw() {
        decoratedShape.draw();
        System.out.println("线条样式是: " + style);
    }

    /**
     * 功能无变化
     */
    @Override
    public void resize() {
        decoratedShape.resize();
    }

    @Override
    public String description() {
        return decoratedShape.description() + " drawn with " + style + " lines.";
    }

    /**
     * 功能无变化
     */
    @Override
    public boolean isHide() {
        return decoratedShape.isHide();
    }

}

创建一个Main程序来执行和测试装饰器代码。

public class Main {

    public static void main(String[] args) {

        Shape rectangle = new Rectangle();
        Shape circle = new Circle();

        System.out.println("开始绘制图形...");
        rectangle.draw();
        circle.draw();
        System.out.println();

        System.out.println("画一个红色、蓝色虚线、厚度为2的圆型 ...");
        Shape circle1 = new FillColorDecorator(new LineColorDecorator(new LineStyleDecorator(
                new LineThinknessDecorator(new Circle(), 2.0d), LineStyle.DASH), Color.BLUE), Color.RED);
        circle1.draw();
        System.out.println();

        //装饰器的顺序在这里也不太重要,因为它们都是独特的功能。
        //我们还可以在单独的语句中嵌套功能。
        System.out.println("在单独的语句中创建具有类似功能的对象。");
        Circle c = new Circle();
        LineThinknessDecorator lt = new LineThinknessDecorator(c, 2.0d);
        LineStyleDecorator ls = new LineStyleDecorator(lt, LineStyle.DASH);
        LineColorDecorator lc = new LineColorDecorator(ls, Color.BLUE);
        FillColorDecorator fc = new FillColorDecorator(lc, Color.RED);
        Shape circle3 = fc;
        circle3.draw();
        System.out.println();

        System.out.println("画一个绿色、黑色线条装饰的圆型...");
        Shape circle2 = new FillColorDecorator(new LineColorDecorator(new Circle(), Color.BLACK), Color.GREEN);
        circle2.draw();
        System.out.println();

        System.out.println("画一个黄色、红色双划线装饰的矩形...");
        Shape rectangle1 = new FillColorDecorator(new LineColorDecorator(new Rectangle(), Color.RED), Color.YELLOW);
        rectangle1.draw();
        System.out.println();

    }

}

程序输出结果:

开始绘制图形...
画个长方形
画个圈圈

画一个红色、蓝色虚线、厚度为2的圆型 ...
画个圈圈
线条宽度是: 2.0
线条样式是: DASH
线条颜色是: BLUE
填充的颜色是: RED

在单独的语句中创建具有类似功能的对象。
画个圈圈
线条宽度是: 2.0
线条样式是: DASH
线条颜色是: BLUE
填充的颜色是: RED

画一个绿色、黑色线条装饰的圆型...
画个圈圈
线条颜色是: BLACK
填充的颜色是: GREEN

画一个黄色、红色双划线装饰的矩形...
画个长方形
线条颜色是: RED
填充的颜色是: YELLOW


Process finished with exit code 0

​ 正如我们所看到的,我们没有更改核心类:ShapeCircleRectangle。而是通过创建包装器和装饰器类,我们添加并定制了ShapeCircleRectangle的行为。

总结

优点

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

缺点

多层装饰比较复杂

使用场景

  1. 扩展一个类的功能。
  2. 动态增加功能,动态撤销。

经典例子

0

评论区