Bootstrap

图解设计模式 (十二)Decorator 模式

读书笔记 仅供参考

简述

Decorator 模式(装饰者模式)是维持装饰边框和装饰物的一致性,为对象增加新的功能,但是它还是原来的对象

UML 和角色

Component

增加功能的核心角色,就像是一块蛋糕(抽象),可以被添加很多奶油和水果。Component 定义了蛋糕的接口(API)。

ConcreteComponent

实现了 Component 角色定义的接口(API)的具体蛋糕。

Decorator

具有与 Component 角色相同的接口(API),在内部保存了被装饰对象—— Component 角色。

ConcreteDecorator

具体的 Decorator 角色

UML

 

例子

UML

//可以显示多行字符串的抽象类
public abstract class Display {
    //获取横向字符数
    public abstract int getColumns();

    //获取纵向行数
    public abstract int getRows();


    //    获取第 row 行的字符串
    public abstract String getRowText(int row);

    public final void show() {
        for (int i = 0; i < getRows(); i++) {
            System.out.println(getRowText(i));
        }
    }
}
//显示单行字符串的类
public class StringDispaly extends Display {
    private String string;

    public StringDispaly(String string) {
        this.string = string;
    }

    @Override
    public int getColumns() {
        return string.getBytes().length;
    }

    @Override
    public int getRows() {
        return 1;
    }

    @Override
    public String getRowText(int row) {
        if (row == 0) {
            return string;
        } else {
            return null;
        }
    }
}
//装饰边框的抽象类,装饰边框和被装饰物具有相同的方法
public abstract class Border extends Display {
    protected Display display;

    protected Border(Display display) {
        this.display = display;
    }
}
//具体的装饰边框,装饰字符串的左右两侧
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;
    }
}
//装饰字符串上下左右
public class FullBorder extends Border {
    protected 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 buffer = new StringBuffer();
        for (int i = 0; i < count; i++) {
            buffer.append(ch);
        }
        return buffer.toString();
    }
}
public class Main {
    public static void main(String[] args) {
        Display b1 = new StringDispaly("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 SideBorder(
                                new FullBorder(
                                        new StringDispaly("Welcome, friend")
                                ), '*'
                        )
                ), '/'
        );
        b4.show();

    }
}

结果

这里写图片描述

 

 

要点

接口(API)的透明性

在 Decorator 模式中,装饰边框与被装饰物具有一致性,两种具有相同的接口(APi)。得益于接口的透明性,Decorator 模式也可以形成递归的结构。

在不改变被装饰物的前提下增加功能。

Decorator 模式使用了委托,可以在不修改被装饰即增加功能。

可以动态地增加功能

缺点

程序中增加许多功能类似的很小的类。

;