【图解设计模式】Decorator模式

不断地为对象添加装饰。

示例

给文字添加装饰边框。

类图

e7tYPP.png

Display类

1
2
3
4
5
6
7
8
9
10
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类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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) {
return row == 0 ? string : null;
}
}

Border类

1
2
3
4
5
6
7
public abstract class Border extends Display {
protected Display display;

protected Border(Display display) {
this.display = display;
}
}

SideBorder类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class SideBorder extends Border {
private char borderChar;

public SideBorder(Display display, char ch) {
super(display);
this.borderChar = ch;
}

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

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

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

FullBorder类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class FullBorder extends Border {
public FullBorder(Display display) {
super(display);
}

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

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

@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类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Main {

public static void main(String[] args) {
Display b1 = new StringDisplay("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 FullBorder(
new SideBorder(
new FullBorder(
new StringDisplay("你好,世界。")),
'*'))),
'/');
b4.show();
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
Hello, world.
#Hello, world.#
+---------------+
|#Hello, world.#|
+---------------+
/+------------------------+/
/|+----------------------+|/
/||*+------------------+*||/
/||*|你好,世界。|*||/
/||*+------------------+*||/
/|+----------------------+|/
/+------------------------+/

登场角色

Component

增加功能时的核心角色。在示例程序中,由Display类扮演此角色。

ConcreteComponent

该角色实现了Component角色所定义的接口(API)。在示例程序中,由StringDisplay类扮演此角色。

Decorator(装饰物)

该角色具有与Component角色相同的接口(API)。在它内部保存了被装饰对象——Component角色。Decorator角色知道自己要装饰的对象。在示例程序中,由Border类扮演此角色。

ConcreteDecorator(具体的装饰物)

该角色是具体的Decorator角色。在示例程序中,由SideBorder类和FullBorder类扮演此角色。

类图

eHPHbj.png