我认为的装饰器模式

简介: 我认为的装饰器模式

装饰器模式

引入

假设有一块🎂,如果涂上奶油,就是奶油蛋糕。如果加上🍓,就是草莓奶油蛋糕。如果加上🍫,蜡烛,就变成了一块生日蛋糕。

不论时蛋糕,奶油蛋糕,草莓奶油蛋糕还是生日蛋糕,他们的核心都是蛋糕。

首先有一个相当于蛋糕的对象,然后不断的装饰当高一样的不断对其增加功能,他就变成了使用更加明确的对象。

像这样不断的为dui'xdui像添加功能的设计模式称为Decorator模式。 Decorator指的是“装饰物”。

事例程序

类的一览表

名字 说明
Display 用于显示字符串的抽象类
StringDisplay 用于显示单行字符的类
Border 用于显示装饰边框的抽象类
SideBorder 用于只显示右边框的类
FullBorder 用于显示上下左右边框的类
Main 测试

类图

image.png

相关类

Display类

  • 抽象类,显示多行字符串
  • getColumns(),抽象方法,获取横向字符数
  • getRows();抽象方法,获取纵向行数
  • getRowText(int row);抽象方法,获取第row行的字符串
  • show() 是显示所有行的字符串的方法,调用getRows()获取行数,调用getRowText(int row)获取需要显示的字符串。show方法使用了getRows和getRowText等抽象方法,这属于模板模式。
public abstract class Display {
    public abstract int getColumns();//获取横向字符数
    public abstract int getRows();//获取纵向行数
    public abstract String getRowText(int row); //获取第row行的字符串
    public final void show() {
        //全部展示
        for (int i = 0; i < getRows(); i++) {
            System.out.println(getRowText(i));
        }
    }
}

StringDisplay类

  • 用于显示单行字符串的类。是Display类的子类,实现display的抽象方法。
  • string保存要显示的字符串。StringDisplay只显示一行字符串,所以getColumns返回string.getBytes().length,getRows返回固定值1。
  • 当获取第0行的时候getRowText才返回string字段。
  • StringDisplay相当于生日蛋糕中的核心🎂。
public class StringDisplay extends Display {
    private String string;   //要显示的字符串
    public StringDisplay(String string) {       //传入要显示的字符串
        this.string = string;
    }
    @Override
    public int getColumns() {       //字符数
        return string.getBytes().length;
    }
    @Override
    public int getRows() { //行数是1
        return 1;
    }
    @Override
    public String getRowText(int row) {   //当row为0返回
        if (row == 0) {
            return string;
        } else {
            return null;
        }
    }
}

Border类

  • 装饰边框的抽象类,Display的子类
  • 通过继承,装饰边框与被装饰物有了相同的方法,具有了一致性
  • Display类型的display字段,表示被装饰物。不过display并不仅限于StringDisplay的实例,因为Border也是Display的子类,display可能是其他装饰边框。
public abstract class Border extends Display {
    protected Display display;//表示被装饰物
    public Border(Display display) {    //在生成实例时通过参数指定被装饰物
        this.display = display;
    }
}

SideBorder类

  • 在字符串两侧装饰边框

效果:

|被装饰物|

public class SideBorder extends Border {
    private char borderChar;
    public SideBorder(Display display, char borderChar) {
        super(display);
        this.borderChar = borderChar;
    }
    @Override
    public int getColumns() {
        return 1 + display.getColumns() + 1;
    }
    @Override
    public int getRows() {
        return display.getRows();
    }
    @Override
    public String getRowText(int row) {
        return borderChar + display.getRowText(row) + borderChar;
    }
}

FullBorder类

  • 在字符串的上下左右都加上装饰边框
public class FullBorder extends Border {
    public FullBorder(Display display) {
        super(display);
    }
    @Override
    public int getColumns() {
        return 1 + display.getColumns() + 1;
    }
    @Override
    public int getRows() {
        return 1 + display.getRows() + 1;
    }
    @Override
    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) {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < count; i++) {
            buf.append(ch);
        }
        return buf.toString();
    }
}

Main

  • b1,显示hello world
  • b2,b1的两侧加上‘#’
  • b3,b2上下左右加上装饰边框
  • b4,给hello world加上多重边框

复制代码

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

效果:

hello world
#hello world#
+-----------+
|hello world|
+-----------+
/+-----------------+/
/|+---------------+|/
/||*+-----------+*||/
/||*|hello world|*||/
/||*+-----------+*||/
/|+---------------+|/
/+-----------------+/

登场角色

  • Component
    增加功能的核心角色,定义蛋糕的接口。——Display
  • ConcreteComponent
    具体的蛋糕。——StringDisplay
  • Decorator
    与Component具有相同的接口,在内部保存了被装饰的对象。——Border
  • ConcreteDecorator
    具体的装饰角色。——SideBorder和FullBorder
目录
相关文章
|
7月前
结构型 装饰器模式
结构型 装饰器模式
35 0
|
7月前
|
设计模式
装饰器模式
装饰器模式
37 0
|
7月前
|
设计模式 C++
【C++】—— 装饰器模式
【C++】—— 装饰器模式
|
设计模式
2023-6-26-第八式装饰器模式
2023-6-26-第八式装饰器模式
79 0
打扮一下(装饰模式)
打扮一下(装饰模式)
70 0
|
前端开发 BI
关于装饰器模式我所知道的
关于装饰器模式我所知道的
82 0
|
设计模式 Java 测试技术
设计模式 - 结构型模式_装饰器模式
装饰器的核⼼就是再**不改原有类**的基础上给类新增功能。 不改变原有类,大家会想到继承、AOP切⾯,当然这些⽅式都可以实现,但是使⽤装饰器模式会是另外⼀种思路更为灵活,可以避免继承导致的⼦类过多,也可以避免AOP带来的复杂性。 很多场景⽤到装饰器模式 `new BufferedReader(new FileReader("")); `字节流、字符流、⽂件流的内容时都⻅到了这样的代码,⼀层嵌套⼀层,⼀层嵌套⼀层,字节流转字符流等等,⽽这样⽅式的使⽤就是装饰器模式的⼀种体现。
124 0
设计模式 - 结构型模式_装饰器模式
|
设计模式
我学会了,装饰器模式
装饰器模式属于结构型模式,这个类型的设计模式总结出了 类、对象组合后的经典结构,将类、对象的结构和使用解耦了,花式的去借用对象。
104 0
我学会了,装饰器模式
装饰模式简单介绍
装饰模式简单介绍
107 0