C++设计模式-装饰器(5)

设计模式:在解决某一类问题场景时,有既定的,优秀的代码框架可以直接使用,其优势如下:

  • 代码更易于维护,代码的可读性,复用性,可移植性,健壮性会更好
  • 当软件原有需求有变更或者增加新的需求时,合理的设计模式的应用,能够做到软件设计要求的开-闭原则,即对修改关闭,对扩展开放,使软件原有功能修改,新功能扩充非常灵活
  • 合理的设计模式的选择,会使软件设计更加模块化,积极的做到软件设计遵循的根本原则高内聚,低耦合

软件设计开-闭原则

开闭原则是软件设计中的一个重要原则,指的是软件实体(如类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在不修改现有代码的基础上,通过扩展新功能来满足新的需求,从而提高软件的灵活性和可维护性

对扩展开放:允许在现有系统中添加新功能

对修改关闭:不需要修改现有的代码来添加新功能,避免引入新错误

通过遵循开闭原则,可以提高代码的可复用性和稳定性。常用的方法包括使用抽象类、接口以及多态等技术

结构型设计模式

结构型设计模式关注类和对象的组合,旨在通过继承或接口来实现更大的结构(继承的概念被用来组合接口和定义组合对象获得新功能的方式)。这些模式帮助确保系统各部分之间的良好组织和交互。以下是一些常见的结构型设计模式

适配器模式(Adapter Pattern)

桥接模式(Bridge Pattern)

组合模式(Composite Pattern)

装饰器模式(Decorator Pattern)

外观模式(Facade Pattern)

享元模式(Flyweight Pattern)

代理模式(Proxy Pattern)



一、装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,允许在不改变对象接口的情况下,动态地扩展对象的功能。这个模式通过创建一个装饰器类来包装原始对象,从而为其添加额外的职责

装饰器模式,与代理模式有相似的地方:装饰器类中有一个公共的抽象基类指针,指向需要增加功能的类;代理模式中,代理类中持有一个抽象公共基类指针指向所委托类的对象

主要角色

组件(Component)– 抽象公共基类:定义了一个接口,可以对具体组件和装饰器进行操作

具体组件(Concrete Component):实现了组件接口,定义了一个基础功能的对象

装饰器(Decorator)持有一个组件对象的引用,并实现组件接口,定义了一个抽象装饰类

具体装饰器(Concrete Decorator):继承自装饰器,添加具体的功能或行为


1.示例代码1

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
142
143
144
145
/************************抽象组件**************************/
class Car{
public:
// 组件接口
virtual void show() = 0;
};
/************************抽象组件**************************/


/************************具体组件**************************/
// 具体组件1
class Bmw:public Car{
// 实现组件接口,实现一个基础功能
void show() override
{
cout << "这是一辆宝马汽车,配置有: 基础配置";
}
};

// 具体组件2
class Audi:public Car{
// 实现组件接口,实现一个基础功能
virtual void show()
{
cout << "这是一辆奥迪汽车,配置有: 基础配置";
}
};

// 具体组件3
class Bnze:public Car{
// 实现组件接口,实现一个基础功能
void show() override
{
cout << "这是一辆奔驰汽车,配置有: 基础配置";
}
};
/************************具体组件**************************/


/************************抽象装饰器**************************/
class Decorator:public Car
{
public:
// 抽象组件指针,指向指针p指向的内容,指针p就是需要增加功能的类的指针
Decorator(Car *p):pCar(p){}
// 实现抽象组件接口
void show() override
{
if(pCar)
{
pCar->show();
}
}
private:
// 持有一个抽象组件指针
Car *pCar;
};
/************************抽象装饰器**************************/


/************************具体装饰器**************************/
// 具体装饰器1
class CarDecorator1:public Decorator
{
public:
CarDecorator1(Car *p): Decorator(p){}
// 实现抽象装饰器基类抽象组件的接口
void show() override
{
// 调用抽象装饰器的方法
Decorator::show();
addBehavior1();
}

private:
// 增加的功能
void addBehavior1(){
cout << ",定速巡航";
}
};

// 具体装饰器2
class CarDecorator2:public Decorator
{
public:
CarDecorator2(Car *p): Decorator(p){}
// 实现抽象装饰器基类抽象组件的接口
void show() override
{
// 调用抽象装饰器的方法
Decorator::show();
addBehavior2();
}

private:
// 增加的功能
void addBehavior2(){
cout << ",自动刹车";
}
};


// 具体装饰器3
class CarDecorator3:public Decorator
{
public:
CarDecorator3(Car *p): Decorator(p){}
// 实现抽象装饰器基类抽象组件的接口
void show() override
{
// 调用抽象装饰器的方法
Decorator::show();
addBehavior3();
}

private:
// 增加的功能
void addBehavior3(){
cout << ",车道偏离";
}
};
/************************具体装饰器**************************/


int main()
{
// 带有基础功能的具体组件1
Car *p1 = new Bmw();
p1->show();
cout << endl;

// 对组件1,增加功能
p1 = new CarDecorator1(p1);
p1->show();
cout << endl;

// 继续增加功能
p1 = new CarDecorator2(p1);
p1->show();
cout << endl;

p1 = new CarDecorator3(p1);
p1->show();
cout << endl;
}

编译运行

1
2
3
4
5
$ (base) zxz@ubuntu:~/Proj/C_C++/DesignPatterns/Decorators$ ./decorators 
这是一辆宝马汽车,配置有: 基础配置
这是一辆宝马汽车,配置有: 基础配置,定速巡航
这是一辆宝马汽车,配置有: 基础配置,定速巡航,自动刹车
这是一辆宝马汽车,配置有: 基础配置,定速巡航,自动刹车,车道偏离

代码框图:

image-20240701150340259


2.示例代码2

其实还可以对抽象装饰器进行省略,直接将具体装饰器从抽象组件进行派生,那么每一个具体组件中也需要显示的持有一个组件指针

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
/************************抽象组件**************************/
class Car{
public:
// 组件接口
virtual void show() = 0;
};
/************************抽象组件**************************/


/************************具体组件**************************/
// 具体组件1
class Bmw:public Car{
// 实现组件接口,实现一个基础功能
void show() override
{
cout << "这是一辆宝马汽车,配置有: 基础配置";
}
};

// 具体组件2
class Audi:public Car{
// 实现组件接口,实现一个基础功能
virtual void show()
{
cout << "这是一辆奥迪汽车,配置有: 基础配置";
}
};

// 具体组件3
class Bnze:public Car{
// 实现组件接口,实现一个基础功能
void show() override
{
cout << "这是一辆奔驰汽车,配置有: 基础配置";
}
};
/************************具体组件**************************/


/************************具体装饰器**************************/
// 具体装饰器1
class CarDecorator1:public Car
{
public:
CarDecorator1(Car *p): pCar(p){}
// 实现抽象装饰器基类抽象组件的接口
void show() override
{
pCar->show();
addBehavior1();
}

private:
// 增加的功能
void addBehavior1(){
cout << ",定速巡航";
}

private:
// 持有一个抽象组件指针
Car *pCar;
};

// 具体装饰器2
class CarDecorator2:public Car
{
public:
CarDecorator2(Car *p): pCar(p){}
// 实现抽象装饰器基类抽象组件的接口
void show() override
{
pCar->show();
addBehavior2();
}

private:
// 增加的功能
void addBehavior2(){
cout << ",自动刹车";
}

private:
// 持有一个抽象组件指针
Car *pCar;
};


// 具体装饰器3
class CarDecorator3:public Car
{
public:
CarDecorator3(Car *p): pCar(p){}
// 实现抽象装饰器基类抽象组件的接口
void show() override
{
pCar->show();
addBehavior3();
}

private:
// 增加的功能
void addBehavior3(){
cout << ",车道偏离";
}

private:
// 持有一个抽象组件指针
Car *pCar;
};
/************************具体装饰器**************************/


int main()
{
// 带有基础功能的具体组件1
Car *p1 = new Bmw();
p1->show();
cout << endl;

// 对组件1,增加功能
p1 = new CarDecorator1(p1);
p1->show();
cout << endl;

// 继续增加功能
p1 = new CarDecorator2(p1);
p1->show();
cout << endl;

p1 = new CarDecorator3(p1);
p1->show();
cout << endl;
}

编译运行

1
2
3
4
5
(base) zxz@ubuntu:~/Proj/C_C++/DesignPatterns/Decorators$ ./decorators 
这是一辆宝马汽车,配置有: 基础配置
这是一辆宝马汽车,配置有: 基础配置,定速巡航
这是一辆宝马汽车,配置有: 基础配置,定速巡航,自动刹车
这是一辆宝马汽车,配置有: 基础配置,定速巡航,自动刹车,车道偏离

代码框架

image-20240701151122656

装饰器模式通过在运行时动态地为对象添加功能,而无需改变对象的结构,提供了比继承更加灵活的解决方案。它是用于增强对象的功能或在不修改客户端代码的情况下对对象进行扩展的强大工具。适合那些需要在运行时添加功能、组合功能或需要灵活扩展功能的场景

3.装饰器模式的类型

基本装饰器(Basic Decorator)

  • 用于在不改变类接口的情况下增加功能,通常为其他装饰器提供基础

具体装饰器(Concrete Decorators)

  • 具体的装饰器实现了附加功能,如 CarDecorator1CarDecorator2

4.优缺点

优点:

动态扩展功能:可以在运行时添加功能,而不需要修改对象的代码

遵循开闭原则:通过增加新装饰器类来扩展功能,而不修改现有代码

灵活性:可以通过不同的装饰器组合来实现各种功能的组合

缺点:

复杂性:装饰器的层次结构可能会变得复杂,增加理解和维护的难度

对象数量增加:使用装饰器会增加系统中的对象数量

适用场景

需要动态地添加功能:在不改变原始对象的情况下添加功能

需要在不同的环境中组合功能:通过组合不同的装饰器来创建不同的功能

需要增加对象的职责:在对象的现有功能基础上添加额外的职责