C++设计模式-适配器(6)

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

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

软件设计开-闭原则

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

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

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

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

结构型设计模式

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

适配器模式(Adapter Pattern)

桥接模式(Bridge Pattern)

组合模式(Composite Pattern)

装饰器模式(Decorator Pattern)

外观模式(Facade Pattern)

享元模式(Flyweight Pattern)

代理模式(Proxy Pattern)



一、适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,它将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

适配器类型有两种形式:

类适配器:使用多重继承来适配接口

对象适配器:使用组合来适配接口

主要角色

目标接口(Target):客户希望使用的接口

适配者(Adaptee):需要适配的接口

适配器(Adapter):将适配者的接口转换成目标接口

1.示例代码

场景

电脑 通过 投影仪 进行投影 ,而投影仪有如下接口:VGAHDMITypeC

正常情况:VGA接口的电脑可以在VGA接口的投影仪上进行投影

不兼容情况:HDMI接口电脑无法在HDMI接口的投影仪进行投影

正常情况

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
#include <iostream>
#include <memory>

using namespace std;

// VGA接口
class VGA{
public:
virtual void play() = 0;
};


// TV01表示支持VGA接口的投影仪
class TV01:public VGA{
public:
void play() override
{
cout << "通过VGA接口连接投影仪,进行视频播放" <<endl;
}
};


// 实现一个电脑类
class HWComputer{
public:
// 该电脑仅仅支持VGA接口
void playVideo(VGA *pVGA)
{
pVGA->play();
}
};

int main()
{
// 创建电脑实例
HWComputer computer;
// 电脑使用支持VGA接口的投影继续视频播放
// new TVO1 是一个支持VGA接口的投影仪实例
computer.playVideo(new TV01);

return 0;
};

不兼容情况

当前存在一批新的投影仪,仅支持HDMI接口,如何解决接口不兼容的问题?

  • 使用对象适配器模式实现,增加类适配器
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
#include <iostream>
#include <memory>

using namespace std;

// VGA接口
class VGA{
public:
virtual void play() = 0;
};


// TV01表示支持VGA接口的投影仪
class TV01:public VGA{
public:
void play() override
{
cout << "通过VGA接口连接投影仪,进行视频播放" <<endl;
}
};


// 实现一个电脑类
class HWComputer{
public:
// 该电脑仅仅支持VGA接口
void playVideo(VGA *pVGA)
{
pVGA->play();
}
};


// HDMI接口
class HDMI{
public:
virtual void play() = 0;
};


// TV02表示支持HDMI接口的投影仪
class TV02:public HDMI{
public:
void play() override
{
cout << "通过HDMI接口连接投影仪,进行视频播放" <<endl;
}
};


/****************************适配器**************************/
class VGAToAdapter:public VGA{
public:
VGAToAdapter(HDMI *p):pHdmi(p){}
void play() override{ // 该方法类似于转换头
pHdmi->play();
}

private:
HDMI *pHdmi;
};
/****************************适配器**************************/


int main()
{
// 创建电脑实例
HWComputer computer;

/*
* 不兼容情况:
* computer.playVideo(new TV02);
* 支持VGA接口的电脑使用HDMI的投影仪进行视频播放,出现接口不兼容情况
* 解决方法:
* 1.代码重构,将HWComputer类的方法playVideo参数VGA *pVGA,更改为 HDMI * 类型
* 但是这样会对原来的代码进行修改,不推荐
* 2.增加一个转换头(适配器),将VGA信号转换为HDMI信号
*/

/********方法2,增加适配器********/
// new TV02 是支持HDMI接口的投影仪
// computer 支持VGA接口的电脑
// 使用适配器,就可以使得 computer 使用 支持HDMI接口的投影仪 进行视频播放
computer.playVideo(new VGAToAdapter(new TV02));

return 0;
};