设计模式之装饰器模式

装饰器模式

概念及作用

  • 动态的将附加组件添加的对象,装饰器为子类化提供了灵活的替代扩展功能
  • 通过递归包装客户端指定的核心对象的装饰
1
2
3
4
5
6
7
8
适配器为其主题提供不同的界面。代理提供相同的接口。 装饰器模式提供增强的界面。
适配器更改了对象的界面,装饰器模式增强了对象的职责。因此,装饰者对客户更加透明。因此,装饰器模式支持递归合成,这对于纯适配器是不可能的。
组合模式和装饰器模式具有相似的结构图,反映了两者都依赖递归合成来组织开放数量的对象。
可以将装饰器视为仅具有一个组件的简并复合。但是,装饰器模式增加了额外的职责 - 它不适用于对象聚合。
装饰器模式旨在让您在不​​进行子类化的情况下向对象添加职责。复合材料的重点不在于装饰,而在于表现。这些意图是截然不同但互补的。因此,组合模式和装饰器模式经常一起使用。
组合模式可以使用责任链让组件通过其父级访问全局属性。它还可以使用装饰器模式在组合的某些部分上覆盖这些属性。
装饰器和代理具有不同的目的但结构相似。两者都描述了如何为另一个对象提供间接级别,并且实现保持对它们转发请求的对象的引用。
装饰器模式允许您更改对象的外观。策略模式可以让你改变内心。

UML图

装饰器模式

优缺点

优点

  • 装饰类和被装饰类可以独立发展,而不会互相耦合
  • 装饰模式的继承关系的一个替代方案.装饰类Decorator装饰多层,返回的对象都是Component(抽象构件),实际上实例化的是具体构件,也就是要装饰的对象!
  • 装饰模式可以动态地扩展一个实现类的功能.

缺点

  • 多层装饰较为复杂

使用场景

  • 需要扩展一个类的功能,或給一个类添加附加功能.当然最好是給多个相关类都添加这个功能的场景.
  • 需要动态給一个对象增加功能,这些功能可以动态地撤销.
  • 需要为一批类进行改装或加装功能.

实例代码

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 1. "lowest common denominator"
interface Widget {
void draw();
}

// 3. "Core" class with "is a" relationship
class TextField implements Widget {
private int width, height;

public TextField(int width, int height) {
this.width = width;
this.height = height;
}
public void draw() {
System.out.println("TextField: " + width + ", " + height);
}
}


// 2. Second level base class with "isa" relationship
abstract class Decorator implements Widget {
// 4. "has a" relationship
private Widget widget;

public Decorator(Widget widget) {
this.widget = widget;
}

// 5. Delegation
public void draw() {
widget.draw();
}
}

// 6. Optional embellishment
class BorderDecorator extends Decorator {
public BorderDecorator(Widget widget) {
super(widget);
}
public void draw() {
// 7. Delegate to base class and add extra stuff
super.draw();
System.out.println(" BorderDecorator");
}
}


// 6. Optional embellishment
class ScrollDecorator extends Decorator {
public ScrollDecorator(Widget widget) {
super(widget);
}
public void draw() {
super.draw(); // 7. Delegate to base class and add extra stuff
System.out.println(" ScrollDecorator");
}
}

public class DecoratorDemo {
public static void main(String[] args) {
// 8. Client has the responsibility to compose desired configurations
Widget widget = new BorderDecorator(new BorderDecorator(new ScrollDecorator(new TextField(80, 24))));
widget.draw();
}
}

C++版的

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
using namespace std;

// 1. "lowest common denominator"
class Widget
{
public:
virtual void draw() = 0;
};


class TextField: public Widget
{
// 3. "Core" class & "is a"
int width, height;
public:
TextField(int w, int h)
{
width = w;
height = h;
}

/*virtual*/
void draw()
{
cout << "TextField: " << width << ", " << height << '\n';
}
};

// 2. 2nd level base class
class Decorator: public Widget // 4. "is a" relationship
{
Widget *wid; // 4. "has a" relationship
public:
Decorator(Widget *w)
{
wid = w;
}

/*virtual*/
void draw()
{
wid->draw(); // 5. Delegation
}
};


class BorderDecorator: public Decorator
{
public:
// 6. Optional embellishment
BorderDecorator(Widget *w): Decorator(w){}

/*virtual*/
void draw()
{
// 7. Delegate to base class and add extra stuff
Decorator::draw();
cout << " BorderDecorator" << '\n';
}
};

class ScrollDecorator: public Decorator
{
public:
// 6. Optional embellishment
ScrollDecorator(Widget *w): Decorator(w){}

/*virtual*/
void draw()
{
// 7. Delegate to base class and add extra stuff
Decorator::draw();
cout << " ScrollDecorator" << '\n';
}
};

int main()
{
// 8. Client has the responsibility to compose desired configurations
Widget *aWidget = new BorderDecorator(new BorderDecorator(new ScrollDecorator
(new TextField(80, 24))));
aWidget->draw();
}

再来一个

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

interface LCD {
void write(String[] s);
void read(String[] s);
}


class Core implements LCD {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

public void write(String[] s) {
System.out.print("INPUT: ");
try {
s[0] = in.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
}

public void read(String[] s) {
System.out.println("Output: " + s[0]);
}
}

class Decorator implements LCD {
private LCD inner;

public Decorator(LCD i) {
inner = i;
}

public void write(String[] s) {
inner.write(s);
}

public void read(String[] s) {
inner.read(s);
}
}

class Scramble extends Decorator {
public Scramble(LCD inner) {
super(inner);
}

public void write( String[] s ) {
super.write(s);
System.out.println("encrypt:");
StringBuilder sb = new StringBuilder(s[0]);
for (int i=0; i < sb.length(); i++) {
sb.setCharAt(i, (char)(sb.charAt(i) - 5));
}
s[0] = sb.toString();
}

public void read(String[] s) {
StringBuilder sb = new StringBuilder(s[0]);
for (int i=0; i < sb.length(); i++) {
sb.setCharAt(i, (char)(sb.charAt(i) + 5));
}
s[0] = sb.toString();
System.out.println( "decrypt:" );
super.read(s);
}
}

public class DecoratorDemo extends Decorator {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

public DecoratorDemo(LCD inner) {
super(inner);
}

public void write(String[] s) {
System.out.print("PASSWORD: ");
try {
in.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
super.write( s );
}

public void read(String[] s) {
System.out.print("PASSWORD: ");
try {
in.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
super.read(s);
}

public static void main(String[] args) {
LCD stream = new DecoratorDemo(new Scramble(new Core()));
String[] str = {""};
stream.write(str);
System.out.println("main: " + str[0]);
stream.read(str);
}
}