适配器模式——C++实现
目录
1. 适配器模式简介
2. 角色组成
3. 代码示例
4. 适配器模式、装饰器模式、外观模式的辨析
1. 适配器模式简介
适配器模式是一种结构型模式。
适配器模式的定义:适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不可兼容的类可以合作无间。
简而言之,适配器模式可以将一种接口转换成我们想要的形式。
举个例子,家用插座的供电时220V交流电,而普通手机的充电口需要的是5V的直流电。它们俩的接口不同,所以不可以通过导线直接连接起来给手机充电。
我们平时使用的手机充电器它的正式名称是电源适配器,电源适配器通过一系列的转换,将220V交流电转换成手机所需要的5V直流电。
手机的充电器就是一种典型的适配器:把一种接口转换成另一种我们需要的接口。
2. 角色组成
- 被适配者:需要被适配的不兼容的对象(比如220V交流电的插座)
- 适配器:充当了接口之间的中间转换角色,将被适配者的接口转换成目标接口(比如手机的电源适配器,将220V交流电的插座转换成5V直流电)
- 目标接口:需要适配的标准接口(我们所需要的目标接口,比如5V直流电接口)
3. 代码示例
有一个鸭子模拟程序,有一个鸭子接口,还有一个火鸡接口,两个接口不同。如果有一个火鸡类,我们想把火鸡类当作鸭子类型使用,但是接口不同,这时候就可以通过适配器模式进行接口转换。
详情请见以下代码:
#if 1
#include <iostream>
using namespace std;
class Duck
{
public:
virtual ~Duck() {}
virtual void quack() = 0;
virtual void fly() = 0;
};
class Turkey
{
public:
virtual ~Turkey() {}
virtual void gobble() = 0;
virtual void fly() = 0;
};
class MallardDuck : public Duck
{
public:
void quack() override
{
cout << "嘎嘎嘎" << endl;
}
void fly() override
{
cout << "我正在飞翔" << endl;
}
};
class WildTurkey : public Turkey
{
public:
void gobble() override
{
cout << "咕咕咕" << endl;
}
void fly() override
{
cout << "我正在飞翔,但我飞行距离很短" << endl;
}
};
class TurkeyAdapter : public Duck
{
public:
TurkeyAdapter(Turkey* turkey) : m_turkey(turkey) {}
void quack() override
{
m_turkey->gobble();
}
void fly() override
{
for (int i = 0; i < 5; i++)
{
m_turkey->fly();
}
}
private:
Turkey* m_turkey;
};
void testDuck(Duck* duck)
{
duck->quack();
duck->fly();
}
int main()
{
Duck* duck = new MallardDuck();
Turkey* turkey = new WildTurkey();
Duck* turkeyAdapter = new TurkeyAdapter(turkey);
testDuck(duck);
cout << "-------------------------" << endl;
testDuck(turkeyAdapter);
delete duck;
delete turkeyAdapter;
delete turkey;
return 0;
}
#endif
通过火鸡适配器,就可以让火鸡来冒充鸭子类型,即便它们的接口并不一样。
4. 适配器模式、装饰器模式、外观模式的辨析
- 装饰器模式:装饰器和适配器模式一样,都是用来包装对象的。装饰器对象可以为context对象增加新的行为和红能,但装饰器对象不会改变原有的接口。
- 适配器模式:适配器模式也会包装对象(包装被适配对象),适配器模式会对调用context对象的接口并作出适当的改变来适应新接口。适配器模式一定会改变原有的接口,继承新接口并包装老接口来实现接口的转换。适配器模式不会增加新的功能,但是一定会进行接口的转换。
- 外观模式:外观模式和适配器模式一样,也会改变接口,但是外观模式改变接口是为了简化接口。外观模式将多个类背后的复杂调用隐藏起来,只暴露出几个干净美好的简单接口给客户端代码。外观模式可以简化客户端代码对复杂子系统的使用过程,客户端无需了解复杂子系统的即可使用,符合最少知识原则。