设计模式之结构型模式(装饰器模式)

装饰者模式 - 装饰边框与被装饰物的一致性。

  1. 装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比承更有弹性,装饰者模式也体现了开闭原则(ocp)
  2. 这里提到的动态的将新功能附加到对象和ocp原则,在后面的应用实例上以代码的形式体现,请同学们注意体会。

类比:
穿衣服是使用装饰的一个例子。 觉得冷时, 你可以穿一件毛衣。 如果穿毛衣还觉得冷, 你可以再套上一件夹克。 如果遇到下雨, 你还可以再穿一件雨衣。 所有这些衣物都 “扩展” 了你的基本行为, 但它们并不是你的一部分, 如果你不再需要某件衣物, 可以方便地随时脱掉。

示例程序
功能是给文字添加装饰边框。
例如为Hello,world加装饰边框。
在这里插入图片描述
类的一览表:

  • Display:用于显示字符串的抽象类
  • StringDisplay:用于显示单行字符串的类
  • Border:用于显示装饰边框的抽象类
  • SideBorder:用于显示左右边框的类
  • FullBorder:用于显示上下左右边框的类。
  • Main:测试程序的类

类图:
在这里插入图片描述
Display:用于显示字符串的抽象类

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:用于显示单行字符串的类

//实现了DisPlay的抽象方法。
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) {//仅当行数为0时返回值
        if(row == 0){
            return string;
        } else {
            return null;
        }
    }
}

Border:用于显示装饰边框的抽象类

//装饰边框的抽象类,通过继承,装饰边框与被装饰五具有相同的方法。意味着他们具有一致性。
public abstract class Border extends Display {
    protected Display display;//表示被装饰物
    protected Border(Display display){
        this.display = display;
    }
}

SideBorder:用于显示左右边框的类

public class SideBorder extends Border{
    private char ch; //装饰边框的字符
    protected SideBorder(Display display, char ch) {
        super(display);
        this.ch = ch;
    }

    @Override
    public int getColumns() {//字符数为字符串数加上两边加的字符数
        return 2 + display.getColumns();
    }

    @Override
    public int getRows() {//只在字符串两边加字符,所以行数不变,直接调用display方法即可
        return display.getRows();
    }

    @Override
    public String getRowText(int row) {
        return ch + display.getRowText(row) + ch;
    }
}

FullBorder:用于显示上下左右边框的类

public class FullBorder extends Border{
    public FullBorder(Display display) {
        super(display);
    }

    @Override
    public int getColumns() {
        return 2 + display.getColumns();//在字符串上下添加字符,行数加2
    }

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

    @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 buffer = new StringBuffer();
        for(int i = 0;i < count;i ++){
            buffer.append(ch);
        }
        return buffer.toString();

    }
}

Main:测试程序的类

public class Main {
    public static void main(String[] args) {
        Display b1 = new StringDisplay("Hello");
        Display b2 = new SideBorder(b1, '#');
        Display b3 =  new FullBorder(b2);
        b1.show();
        System.out.println();
        b2.show();
        System.out.println();
        b3.show();
    }
}
  1. 部件 (Component) 声明封装器和被封装对象的公用接口。
  2. 具体部件 (Concrete Component) 类是被封装对象所属的类。 它定义了基础行为, 但装饰类可以改变这些行为。
  3. 基础装饰 (Base Decorator) 类拥有一个指向被封装对象的引用成员变量。 该变量的类型应当被声明为通用部件接口, 这样它就可以引用具体的部件和装饰。 装饰基类会将所有操作委派给被封装的对象。
  4. 具体装饰类 (Concrete Decorators) 定义了可动态添加到部件的额外行为。 具体装饰类会重写装饰基类的方法, 并在调用父类方法之前或之后进行额外的行为。
  5. 客户端 (Client) 可以使用多层装饰来封装部件, 只要它能使用通用接口与所有对象互动即可。

装饰模式适合应用场景

  1. 如果你希望在无需修改代码的情况下即可使用对象, 且希望在运行时为对象新增额外的行为, 可以使用装饰模式。

  2. 装饰能将业务逻辑组织为层次结构, 你可为各层创建一个装饰, 在运行时将各种不同逻辑组合成对象。 由于这些对象都遵循通用接口, 客户端代码能以相同的方式使用这些对象。

  3. 如果用继承来扩展对象行为的方案难以实现或者根本不可行, 你可以使用该模式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值