3 结构型设计模式
结构型设计模式,描述处理类和对象间的组合,帮助将多个对象组织成更大的结构。
结构型设计模式主要包括:适配器模式、桥接模式、过滤器模式、组合模式、装饰器模式、外观模式、享元模式、代理模式八种。
3.1 适配器模式
“没有什么问题是加一层不能解决。”
将一个接口转换为客户端所期待的接口,从而使两个接口不兼容的类可以一起工作。
适配器模式还有个别名,Wrapper(包装器),就是将目标类用一个新类包装,相当于在客户端与目标类直接加一层。
3.1.1 使用场景
1)当需要使用一个现存的类,但它提供的接口与所需系统不兼容,该类的内容不能被改变;
2)当多个团队独立开发系统的各功能模块,由于某些原因不能确定接口时,但需要组合起来。
3)新旧API兼容(大型使用库的升级);
4)三方包适配;
5)统一多个类的接口;
3.1.2 解决思路
考虑采用继承或依赖。
3.1.3 优点与缺点
1)优点:
1.1)使任何两个没有关联的类可以一起运行;
1.2)提高类的复用性;
1.3)增加类的透明度;
1.4)灵活性好;
2)缺点:
2.1)过多使用适配器,会使系统非常凌乱,不容易整体把握;
3.1.4 实现
3.1.4.1 类模式——适配器模式
该模式的实现使用了继承机制,即适配器同时继承两个对象的接口。注:该方式仅能在支持多重继承的编程语言中实现,例如C++。
1) 例子:
主机只有USB插头的接口,而我们手中只有一个ps2插头的设备,利用适配器模式将ps2接口转换为usb接口。
2) 类定义:
2.1)Target(目标抽象类):目标抽象类定义客户所需的接口,可以是一个抽象类,也可以是具体类;
2.2)Adapter(适配器类):可以调用另一种接口,作为一个转换器,对Adaptee和Target进行继承,是适配器模式的核心;
2.3)Adaptee(适配者类):适配者,即被适配的角色,其定义了一个已经存在的接口,该接口需要适配。适配者类是客户希望的业务方法。
3) 示意图
4) 实现
实现以3.1.4.1中的例子作为考虑的场景
4.1) USB (Target)
class Usb {
public:
virtual void isUsb();
};
4.2) Ps2 (Adatee)
class Ps2 {
public:
void isPs2();
};
4.3) Adapter (类适配器)
class Adapter : public Usb, public Ps2 {
public:
void isUsb() { isPs2(); }
};
4.4) Client (用户使用)
int main()
{
Usb* usb = new Adapter();
usb->isUsb();
return 0;
}
3.1.4.2 对象模式——适配器模式
对象模式主要应用于在旧的接口基础上,添加新的接口的行为上,所以通常采用继承于旧的接口,同时新增新的接口相关特性。该对象模式主要应用继承,相较于类模式,其仅需要单继承。
总结来说,对象模式——适配器模式,对一个对象的接口进行实现,并对另一个对象进行封装。
1) 例子
我们已经拥有Deque类,需要适配Queue类,我们可以在Deque类的基础上通过Adapter实现使用Queue的函数接口,实质上调用Deque的函数实现。
2) 类定义
2.1)Target(目标抽象类,即旧的API):目标抽象类可以是一个抽象接口类,也可以是一个具体类
2.1.1)成员函数:
·所需方法的虚函数;
2.2)Adapter(适配器类,即我们最后需要的)
2.2.1)成员函数:
·对接口类的方法进行重写;
2.2.2)成员变量:
·适配者对象;
2.3)Adaptee(适配者类,即被适配的角色),该类为一个已经存在的类。
3) 示意图
4) 实现
此处采用3.1.4.2中的例子。
4.1) Queue (Target)
class Queue {
public:
Queue();
virtual void push(T t) = 0;
virtual void pop() = 0;
};
4.2) Deque (Adaptee)
class Deque{
public:
Deque();
void pop_back();
void pop_front();
void push_back(T t);
void push_front(T t);
};
4.3) Adapter (类适配器)
class Adapter : public Queue{
public:
Queue();
void pop() { m_pDeque->pop_front(); }
void push(T t) { m_pDeque->push_back(t); }
private:
Deque *m_pDeque;
};
4.4) Client (用户使用)
int mian()
{
Queue *queue = new Adapter();
queue->push(t);
queue->pop();
delete queue;
return 0;
}
参考网址
[1] https://blog.csdn.net/yxh_1_/article/details/116085949 (适配器模式)
[2] https://zhuanlan.zhihu.com/p/369272002 适配器模式)
[3] https://blog.csdn.net/Bing_Lee/article/details/95231409 适配器模式)
[4] https://blog.csdn.net/xyisv/article/details/97797837?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-97797837-blog-116085949.pc_relevant_vip_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-97797837-blog-116085949.pc_relevant_vip_default&utm_relevant_index=3 (适配器模式)