【java学习笔记】设计模式12——Decorator(装饰物)模式

该文章是阅读《图解设计模式》的学习笔记。书本链接https://www.ituring.com.cn/book/1811

如现在有几块方形面包,你可以加入火腿鸡蛋并切成三角形状做成一个三明治;或者加入火腿牛肉块芝士并切成原型形状做成一个汉堡包。但无论你是制作三明治还是汉堡包,它的核心都是方形面包,只是加上了牛肉块火腿鸡蛋芝士这些材料进行装饰,让面包变得更美味。我们也可以采用这种思想进行编程,一个相当于方形面包的对象,然后不断编写代码引入新功能装饰这个对象,让该对象的功能变得更具体,变成一个更加明确的对象。像这种不断为对象添加装饰的模式被称为Decorator(装饰物)模式。

Display抽象类代码:
package com.wen.Decorator;

public abstract class Display {
    public abstract int getColumns();
    public abstract int getRows();
    public abstract String getRowText(int row);

    public final void show(){
        for(int i=0;i<getRows();i++){
            System.out.println(getRowText(i));
        }
    }
}

StringDisplay类代码:

package com.wen.Decorator;

public abstract class Display {
    public abstract int getColumns();
    public abstract int getRows();
    public abstract String getRowText(int row);

    public final void show(){
        for(int i=0;i<getRows();i++){
            System.out.println(getRowText(i));
        }
    }
}

Border抽象类代码:

package com.wen.Decorator;

public abstract class Border extends Display{
    protected Display display;
    protected Border(Display display){
        this.display = display;
    }
}
SideBorder类代码:
package com.wen.Decorator;

public class SideBorder extends Border {
    private char borderChar;

    public SideBorder(Display display, char borderChar) {
        super(display);
        this.borderChar = borderChar;
    }

    @Override
    public int getColumns() {
        return display.getColumns()+2;//有左右两边所以列数加2
    }

    @Override
    public int getRows() {
        return display.getRows();
    }

    @Override
    public String getRowText(int row) {
        return borderChar+display.getRowText(row)+borderChar;//拼合两边的字符组成字符串
    }
}
FullBorder类代码:
package com.wen.Decorator;

public class FullBorder extends Border {
    public FullBorder(Display display) {
        super(display);
    }
    public int getColumns() {                   //左右边界加两列
        return display.getColumns() + 2;
    }
    public int getRows() {                      //上下边界加两行
        return display.getRows()+2;
    }
    public String getRowText(int row) {         // 指定的那一行的字符串
        if (row == 0) {                                                 // 上边框
            return "+" + makeLine('-', display.getColumns()) + "+";
        } else if (row == display.getRows() + 1) {                      // 下边框
            return "+" + makeLine('-', display.getColumns()) + "+";
        } else {                                                        // 其他边框
            return "|" + display.getRowText(row - 1) + "|";
        }
    }
    private String makeLine(char ch, int count) {         // 生成一个重复count次字符ch的字符串
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < count; i++) {
            buf.append(ch);
        }
        return buf.toString();
    }
}

Main入口类代码:

package com.wen.Decorator;

public class Main {
    public static void main(String[] args) {
        Display b1 = new StringDisplay("Hello, world.");
        Display b2 = new SideBorder(b1, '#');
        Display b3 = new FullBorder(b2);
        b1.show();
        b2.show();
        b3.show();
        Display b4 =
                    new SideBorder(
                        new FullBorder(
                            new FullBorder(
                                new SideBorder(
                                    new FullBorder(
                                        new StringDisplay("你好,世界。")
                                    ),
                                    '*'
                                )
                            )
                        ),
                        '/'
                    );
        b4.show();
    }
}

模式中的角色:

Component(组件):增加功能时的核心角色,以上面的代码为例Display属于该角色。里面定义了显示字符串所需的方法。

ConcreteComponent(具体的组件):负责实现组件类定义的接口,上边代码中StringDisplay负责显示字符串的类代码此角色。

Decorator(装饰物):该角色内部包含了被装饰的Component组件角色,并具有与Component角色相同的方法。

ConcreteDecorator(具体的装饰物):负责实现Decorator角色定义的装饰方法。

发布了54 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/baidu_35800355/article/details/105473240