装饰者

  • 装饰者模式
    • 动机

      在某些情况下我们可能会”过度的使用继承来扩展对象的功能”,由于继承为类型引入静态特质,使得这种扩展方式缺乏灵活性。并且随着子类的增多(扩展功能的增多),使各子类的组合(扩展功能的组合)会导致更多子类的膨胀

装饰者模式

例子

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
class Stream{
public:
virtual char Read(int number)=0;
virtual void Seek(int position)=0;
virtual void Write(char data)=0;

virtual ~Stream();
};

class FileStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

class NetworkStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

class MemoryStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

// 加密
class CryptoNetworkStream:public NetworkStream{
public:
virtual char Read(int number){
NetworkStream::read(number);
//额外加密
}
virtual void Seek(int position){
//额外加密
NetworkStream::Seek(position);
}
virtual void Write(char data){
//额外加密
NetworkStream::Seek(data);
}
}

class CryptoFileStream:public FileStream{
public:
virtual char Read(int number){
FileStream::read(number);
//额外加密
}
virtual void Seek(int position){
//额外加密
FileStream::Seek(position);
}
virtual void Write(char data){
//额外加密
FileStream::Seek(data);
}
}

class CryptoMemoryStream:public MemoryStream{
public:
virtual char Read(int number){
MemoryStream::read(number);
//额外加密
}
virtual void Seek(int position){
//额外加密
MemoryStream::Seek(position);
}
virtual void Write(char data){
//额外加密
MemoryStream::Seek(data);
}
}

class BufferedMemoryStream : public MemoryStream{
//.....
}
class BufferedFileStream : public FileStream{
//.....
}
class BufferedNetworkStream : public NetworkStream{
//.....
}

class CryptoBufferedMemoryStream : public CryptoMemoryStream{
//.....
}
class CryptoBufferedFileStream : public CryptoFileStream{
//.....
}
class CryptoBufferedNetworkStream : public CryptoNetworkStream{
//.....
}

子类图示

初版图示

问题

  • 子类过多,同时存在大量重复的代码

改进

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

class Stream{
public:
virtual char Read(int number)=0;
virtual void Seek(int position)=0;
virtual void Write(char data)=0;

virtual ~Stream();
};

class FileStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

class NetworkStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

class MemoryStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

// 加密
class CryptoNetworkStream{
// step 1 NetworkStream* networkStream;
// step 2 Stream* networkStream = new NetworkStream()
// step 3
Stream* stream;
public:
virtual char Read(int number){
//step 3 networkStream::read(number);
stream->read(number);

//额外加密
}
virtual void Seek(int position){
//额外加密
//step 3 NetworkStream::Seek(position);
stream->Seek(position);
}
virtual void Write(char data){
//额外加密
//step 3 NetworkStream::Seek(data);
stream->Seek(position);
}
}

class CryptoFileStream{
// step 1 FileStream* fileStream;
// step 2 Stream* fileStream = new FileStream()
// step 3
Stream* stream;
public:
virtual char Read(int number){
//step 3 FileStream::read(number);
stream->read(number);
//额外加密
}
virtual void Seek(int position){
//额外加密
//step 3 FileStream::Seek(position);
stream->Seek(position);
}
virtual void Write(char data){
//额外加密
//step 3 FileStream::Seek(data);
stream->Seek(position);
}
}

class CryptoMemoryStream{
// step 1 MemoryStream* memoryStream;
// step 2 Stream* memoryStream = new MemoryStream()
// step 3
Stream* stream;
public:
virtual char Read(int number){
//step 3 MemoryStream::read(number);
//额外加密
stream->read(number);
}
virtual void Seek(int position){
//额外加密
//step 3 MemoryStream::Seek(position);
stream->Seek(position);
}
virtual void Write(char data){
//额外加密
//step 3 MemoryStream::Seek(data);
stream->Write(position);
}
}


class BufferedMemoryStream : public MemoryStream{
//.....
}
class BufferedFileStream : public FileStream{
//.....
}
class BufferedNetworkStream : public NetworkStream{
//.....
}

class CryptoBufferedMemoryStream : public CryptoMemoryStream{
//.....
}
class CryptoBufferedFileStream : public CryptoFileStream{
//.....
}
class CryptoBufferedNetworkStream : public CryptoNetworkStream{
//.....
}

整理

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
102
103
104
105
106
107
108
109
110
111

class Stream{
public:
virtual char Read(int number)=0;
virtual void Seek(int position)=0;
virtual void Write(char data)=0;

virtual ~Stream();
};

class FileStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

class NetworkStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

class MemoryStream:public Stream{
public:
virtual char Read(int number){

}
virtual void Seek(int position){

}
virtual void Write(char data){

}
}

// 加密
class CryptoStream:public Stream{ // 用于规范类实现的接口的

Stream* m_stream;
public:
virtual char Read(int number){
stream->read(number);
//额外加密
}
virtual void Seek(int position){
//额外加密
stream->Seek(position);
}
virtual void Write(char data){
//额外加密
stream->Seek(position);
}

// CryptoStream(Stream* stream){
// this->m_stream = stream;
// }
// 没有使用初始化参数模板故进行修改
CryptoStream(Stream* stream):m_stream(stream){
}

}

class BufferedStream : public Stream{
//.....
Stream* m_stream;
public:
virtual char Read(int number){
stream->read(number);
//缓冲
}
virtual void Seek(int position){
//缓冲
stream->Seek(position);
}
virtual void Write(char data){
//缓冲
stream->Seek(position);
}

// CryptoStream(Stream* stream){
// this->m_stream = stream;
// }
// 没有使用初始化参数模板故进行修改
BufferedStream(Stream* stream):m_stream(stream){
}
}

// 运行时装配

//使用 FileStream
CryptoStream* fileCryptonStream = new CryptoStream(new FileStream());
CryptoStream* networkCryptonStream = new CryptoStream(new NetworkStream());
CryptoStream* memoryCryptonStream = new CryptoStream(new MemoryStream());

//使用CryptoBufferedStream
BufferedStream* cryptoBufferFileStream = new BufferedStream(new CryptoStream(new FileStream()))

进一步改进

  • 因为具有公共父类的子类中都含有某一对象
    • 顾应该将其抽象到父类中
    • 但 FileStream 并不需要 m_stream 因为他是自己来实现功能那个的。顾新建一个子类 DecoratorStream
      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

      class Stream{
      public:
      virtual char Read(int number)=0;
      virtual void Seek(int position)=0;
      virtual void Write(char data)=0;

      virtual ~Stream();
      };

      class FileStream:public Stream{
      public:
      virtual char Read(int number){

      }
      virtual void Seek(int position){

      }
      virtual void Write(char data){

      }
      }

      class NetworkStream:public Stream{
      public:
      virtual char Read(int number){

      }
      virtual void Seek(int position){

      }
      virtual void Write(char data){

      }
      }

      class MemoryStream:public Stream{
      public:
      virtual char Read(int number){

      }
      virtual void Seek(int position){

      }
      virtual void Write(char data){

      }
      }

      class DecoratorStream:public Stream{
      protected:
      Stream* m_stream;

      public:
      DecoratorStream(Stream* stream):m_stream(stream){

      }
      }
      class CryptoStream:public DecoratorStream{ // 用于规范类实现的接口的
      public:
      virtual char Read(int number){
      stream->read(number);
      //额外加密
      }
      virtual void Seek(int position){
      //额外加密
      stream->Seek(position);
      }
      virtual void Write(char data){
      //额外加密
      stream->Seek(position);
      }

      CryptoStream(DecoratorStream* stream):m_stream(stream){
      }

      }

      class BufferedStream : public DecoratorStream{
      public:
      virtual char Read(int number){
      stream->read(number);
      //缓冲
      }
      virtual void Seek(int position){
      //缓冲
      stream->Seek(position);
      }
      virtual void Write(char data){
      //缓冲
      stream->Seek(position);
      }

      BufferedStream(DecoratorStream* stream):m_stream(stream){
      }
      }

      改进后图示

      终版图示

UML图

UML图

模式定义

动态(组合)的给一个对象增加一些额外的职责。就增加功能而言

  • Docorator比生成子类(继承)更加灵活
    • 消除重复代码
    • 减少子类个数

要点总结

  • 通过采用组合而非继承的手法,Decorator 模式实现了在运行时动态扩展对象的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类延伸问题”
  • Decorator 类在接口表现为 “is-a” Component的继承关系,但在实现上又表现为 “has-a” Component 的组合关系。及Decorator 类又实用了另外一个Component类
  • Decorator 模式的目的并非解决“多子类衍生的多继承“问题,Decorator 模式应用的要点在于解决”主体类在多个方向上的扩展功能“—”装饰“的含义