Decorator定义:
动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.
为什么使用Decorator?
我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的.
使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了"即插即用"的方法,在运行期间决定何时增加何种功能.
程序举例:
Display.java:
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));
}
}
}
Border .java:
public abstract class Border extends Display {
protected Display display; // 指装饰外框里面的「內容」??
protected Border(Display display) { // 在产生对象实例时,以参数指定「內容」
this.display = display;
}
}
StringDisplay .java:
public class StringDisplay extends Display {
private String string; // 打印的字串
public StringDisplay(String string) { // 以参数指定打印的字串
this.string = string;
}
public int getColumns() { // 字数
return string.getBytes().length;
}
public int getRows() { // 行数为1
return 1;
}
public String getRowText(int row) { // 仅在row为0时才返回
if (row == 0) {
return string;
} else {
return null;
}
}
}
SideBorder.java:
public class SideBorder extends Border {
private char borderChar; // 装饰字符
public SideBorder(Display display, char ch) { // 以构造子指定Display和装饰字符
super(display);
this.borderChar = ch;
}
public int getColumns() { // 字数要再加上內容两边的装饰字符
return 1 + display.getColumns() + 1;
}
public int getRows() { // 行数同內容的行数
return display.getRows();
}
public String getRowText(int row) { // 指定该行的內容即为在內容之指定行的两边
// 加上装饰字符
return borderChar + display.getRowText(row) + borderChar;
}
}
UpDownBorder .java:
public class UpDownBorder extends Border {
private char borderChar; // 装饰字符
public UpDownBorder(Display display, char ch) { // 以构造子指定Display和装饰字符
super(display);
this.borderChar = ch;
}
public int getColumns() { // 字数同內容的字数
return display.getColumns();
}
public int getRows() { // 行数要再加上內容上下的装饰字符的行数
return 1 + display.getRows() + 1;
}
public String getRowText(int row) { // 指定该行的內容
if (row == 0 || row == getRows() - 1) {
return makeLine(borderChar, getColumns());
} else {
return display.getRowText(row - 1);
}
}
private String makeLine(char ch, int count) { // 以字符ch,建立重复count次的连续字串
StringBuffer buf = new StringBuffer();
for (int i = 0; i < count; i++) {
buf.append(ch);
}
return buf.toString();
}
}
Main.java:
public class Main {
public static void main(String[] args) {
Display b1 = new StringDisplay("Hello, world.");
Display b2 = new UpDownBorder(b1, '-');
Display b3 = new SideBorder(b2, '*');
b1.show();
b2.show();
b3.show();
Display b4 =
new FullBorder(
new UpDownBorder(
new SideBorder(
new UpDownBorder(
new SideBorder(
new StringDisplay("您好。"),
'*'
),
'='
),
'|'
),
'/'
)
);
b4.show();
}
}
注意:display继承类中的getRowText方法
这个方法把所有的用法都继集成到一起