假如现在有一块蛋糕, 加上奶油就是奶油蛋糕。如果继续再加上草莓,就是草莓蛋糕,再加点蜡烛,就变成了生日蛋糕。不论是蛋糕、奶油蛋糕、草莓蛋糕还是生日蛋糕,它们的核心都是蛋糕。
像这样不断地为对象添加装饰的设计模式被称为Decorator模式。
这个添加的过程有点类似于套娃。就是一个很原始的对象,一直在它外层套东西,不断地装饰它。
示例程序的功能是给文字添加装饰边框,这里所谓的装饰边框是指用"-“,”+“,”|"等字符组成的边框。
Component角色,抽象的”被装饰对象“,增加功能时的核心角色,比如定义了三个抽象方法,分别是获取字符串数组的列数,行数,以及输出第几行。还有一个默认方法是输出全部行
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));
}
}
}
ConcreteComponent角色,具体的被装饰对象
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() {
return 1;
}
@Override
public String getRowText(int row) {
if (row == 0) {
return string;
} else {
return null;
}
}
}
Decorator(装饰物)角色,该角色具有与Component角色相同的接口(API),在它内部保存了被装饰对象——Component角色
public abstract class Border extends Display {
protected Display display; // 表示被装饰物
public Border(Display display) {
this.display = display;
}
}
ConcreteDecorator(具体的装饰物)
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 {
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();
}
}
测试类
public class Test {
public static void main(String[] args) {
Display d1 = new StringDisplay("hello,world");
Display d2 = new UpDownBorder(d1, '-');
d2.show();
Display d4 = new FullBorder(
new UpDownBorder(
new SideBorder(
new UpDownBorder(
new SideBorder(
new StringDisplay("helloWorld")
, '*'
),'='
), '/'
), '|'
)
);
d4.show();
}
}
在Decorator模式中,装饰边框与被装饰物具有一致性,类似于Composite模式。不过,Decorator模式虽然与Composite模式一样,都具有递归结构,但是他们的使用目的不同,Decorator模式的主要目的是通过添加装饰物来增加对象的功能。