0%

装饰器模式

装饰器模式简介

装饰器模式可以为已有类的方法增加新的行为,例如为一个文件数据读写类的写数据方法增加数据加密的行为。而实现的策略不是基于继承自这个已有的类。

装饰器模式通常代码结构

代码示例

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
//interface
class DataManipulable {
public:
virtual size_t writeData(const char * data) = 0;
virtual size_t readData(char * buffer, size_t len) = 0;
};

class BaseFileDataManipulator: public DataManipulable {
private:
const std::string _filename;
public:
BaseFileDataManipulator(const std::string & filename): _filename(filename) {}

size_t writeData(const char * data) override {
//write data to file
}

size_t readData(char * buffer, size_t len) {
//read data from file
}
};

//decorator interface
class DataManipulableDecorator: public DataManipulable {
private:
DataManipulable & _dataManipulator;
public:
DataManipulableDecorator(DataManipulable & dataManipulator): _dataManipulator(dataManipulator) {}
DataManipulable & getManipulator() {
return _dataManipulator;
}
};

//concrete decorators
class EncryptDataManipulator: public DataManipulableDecorator {
public:
EncryptDataManipulator(DataManipulable & dataManipulator): DataManipulable(dataManipulator) {}
size_t writeData(const char * data) override {
//encrypt data first

//then delegate to _dataManipulator
return this->getManipulator().writeData(data);
}

size_t readData(char * buffer, size_t len) override {
//delegate to _dataManipulator
size_t readLen = this->getManipulator().readData(buffer, len);

//do decrypt data operation

return readLen;
}
};

class CompressDataManipulator: public DataManipulableDecorator {
public:
CompressDataManipulator(DataManipulable & dataManipulator): DataManipulableDecorator(dataManipulator) {}

size_t writeData(const char * data) override {
//compress data first

//then delegate to _dataManipulator
return this->getManipulator().writeData(data);
}

size_t readData(char * data, size_t len) {
//delegate to _dataManipulator
size_t readLen = this->getManipulator().readData(buffer, len);

//do decompress operation

return readLen
}
};

在上例中,BaseFileDataManipulator是一个已有基本功能的数据读写类,而EncryptDataManipulator和CompressDataManipulator分别用于给已有的数据读写类增加加密数据和压缩数据的能力。EncryptDataManipulator和CompressDataManipulator并没有继承自BaseFileDataManipulator,而是继承自DataManipulableDecorator这个接口类。但是BaseFileDataManipulator和DataManipulableDecorator都继承自DataManipulable这个接口类。客户端只关心和DataManipulable中定义的接口即可。

和适配器模式的对比

  • 适配器模式一般用于对已有对象的接口进行修改或者增加新的接口,而适配器模式一般不会改变已有对象的接口,而是对已有对象的接口的实现上添加新的行为。