我认为的装饰器模式

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

装饰器模式

引入

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

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

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

像这样不断的为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
目录
相关文章
|
6月前
|
设计模式 存储 缓存
聊聊Java设计模式-装饰器模式
装饰器模式允许向一个现有的对象添加新的功能,同时不改变其结果。比如Java 中的IO框架中,`FileInputStream`(处理文件)、`ByteArrayInputStream`(处理字节数组)、`BufferedInputStream`(带缓存的处理类)等就是对`InputStream`进行的功能扩展,这就是装饰器模式的典型应用。
61 1
聊聊Java设计模式-装饰器模式
|
6月前
结构型 装饰器模式
结构型 装饰器模式
32 0
|
2月前
|
设计模式 Java
Java设计模式-装饰器模式(10)
Java设计模式-装饰器模式(10)
|
4月前
|
设计模式
对于装饰器模式与代理模式的个人理解
摘要: 代理模式与装饰器模式虽相似,但目的不同。装饰器动态增强对象功能,如添加新特性,而不改变原有类。代理模式则用于控制访问,如优化昂贵操作或添加辅助服务(如日志),它可能在内部初始化原对象。用法上,装饰器由外部决定是否应用,允许链式创建,而代理通常内部调用,外部直接与代理交互,被代理对象可能独立不可用。
|
6月前
|
设计模式
装饰器模式
装饰器模式
33 0
|
6月前
|
设计模式 C++
【C++】—— 装饰器模式
【C++】—— 装饰器模式
|
设计模式 Java
装饰器模式【Java设计模式】
装饰器模式【Java设计模式】
63 0
|
设计模式
2023-6-26-第八式装饰器模式
2023-6-26-第八式装饰器模式
75 0