设计模式-装饰器模式

装饰器模式

定义

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

类图

装饰器模式类图

Component

增加功能时的核心角色

ConcreteComponent

实现了Component角色所定义的接口

Decorator(装饰物)

具有和Component相同的接口,在它内部保存了被装饰对象-Component。它知道自己要装饰的对象。

ConcreteDecorator(具体的装饰物)

具体的Decorator。

示例

类图

装饰器模式示例类图

Border

1
2
3
4
5
6
7
public abstract class Border extends Display {
protected Display display;
protected Border(Display display) {
this.display = display;
}
}

Display

1
2
3
4
5
6
7
8
9
10
11
public abstract class Display {
public abstract int getColumns();
public abstract int getRows();
public abstract String getRowText(int row);
public void show() {
for (int i = 0; i < getRows(); i++) {
System.out.println(getRowText(i));
}
}
}

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
public class FullBorder extends Border {
public FullBorder(Display display) {
super(display);
}
public int getColumns() {
return 1 + display.getColumns() + 1;
}
public int getRows() {
return 1 + display.getRows() + 1;
}
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();
}
}

SideBorder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SideBorder extends Border {
private char borderChar;
public SideBorder(Display display, char ch) {
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;
}
}

StringDisplay

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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() {
return 1;
}
public String getRowText(int row) {
if (row == 0) {
return string;
} else {
return null;
}
}
}

Main

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
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("StringDisplay")
),
'*'
)
)
),
'/'
);
b4.show();
}
}

总结

在Decorator模式中,装饰边框与被装饰物具有相同的接口。虽然接口是相同的,但是越装饰,功能则越多。此时我们完全不需要对被装饰的类做任何修改。这样就实现了不修改被装饰的类即可增加功能

Decorator模式中使用到了委托,它是类之间形成了弱关联关系。因此,不用改变框架代码,就可以生成一个与其他对象具有不同关系的新对象。

0%