您的位置:首页 > 编程语言 > C语言/C++

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

2010-08-27 00:17 316 查看
定义:

将一个类的接口转换成客户需要的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。也称作包装器(Wrappter)。

结构
对象适配器(Object Adapter),使用对象组合方式:



类适配器(Class Adapter),使用类继承方式:



理解
1. Target是供Client调用的抽象基类。
2. Adaptee是需要适配的类(适配者类)。Adaptee的方法(SpecificRequest)与Target的方法(Request)是不兼容的。
3. Adapter是适配器类。完成对Target和Adaptee的接口适配工作。Adapter重新实现Request方法,内部隐藏了调用Adaptee不兼容方法(SpecificRequest)的细节。
4. 类适配器是通过继承类适配者类(Adaptee)实现的。类适配器实现客户类所需要的方法(SpecificRequest)。当客户对象调用适配器类(Adapter)方法的时候,适配器内部调用它所继承的适配者的方法。
5. 对象适配器包含一个适配器者的引用,与类适配器相同,对象适配器也实现了客户类需要的接口。当客户对象调用对象适配器的方法的时候,对象适配器调它所包含的适配器者实例的适当方法。对象组合方式,允许一个Adapter适配多个Adaptee。

要点
1. 适配器模式适用于:
你想使用一个已经存在的类,而它的接口不符合你的需求。
你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
(仅适用于对象适配器)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
2. C++使用类适配器时,Adapter类使用public方式继承Target类,并使用private方式继承Adaptee类。这样,Adapter是Target子类型,但不是Adaptee子类型。如此这般,推荐使用对象适配器方式。
3. 适配器模式与桥接(Bridge)模式的区别。桥接模式的目的是将接口部分与实现分离,从而使它们能相对独立的改变;桥接是设计阶段行为。适配器模式是对已有接口的改变,使得功能相同但接口不兼容的类桥接在一起。

应用
在中国大陆,使用中式插座(CCnOutlet)。买了一个水货手机,但充电器使用英式插座(CEnOutlet)。要想在中式插座上给手机充电,就得买一个插座转换器(CCnOutletAdapter)来,使两个不匹配的接口可以正常工作。插座转换器就是适配器(Adapter),英式插座是适配者(Adaptee)。
源码中使用对象适配器方式,这样的好处是,适配器可以有多个适配者,譬如我要兼容美式插座,只需要新增美式插座CUsOutlet,并且将CUsOutlet作为CCnOutletAdapter的成员即可。

源码
#include <iostream>
#include <string>
using namespace std;

//适配器基类Target, 中式插座
class CCnOutlet
{
public:
virtual ~CCnOutlet(){};

virtual void CnPlug(){};
};

//适配者Adaptee, 英式插头
class CEnOutlet
{
public:
void EnPlug()
{
cout << "use en plug" << endl;
}
};

//适配器Adapter. 使用对象适配器方式
class CCnOutletAdapter : public CCnOutlet
{
public:
CCnOutletAdapter(CEnOutlet* pEnOutlet) : m_pEnOutlet(pEnOutlet) {};

virtual ~CCnOutletAdapter(){};

virtual void CnPlug()
{
cout << "wanna use cn plug" << endl;
cout << "adapter transfer …" << endl;
m_pEnOutlet->EnPlug();
}

protected:
CEnOutlet* m_pEnOutlet;
};

int main()
{
//适配者当作参数传递给适配器,完成适配过程
CEnOutlet* pEnOutlet = new CEnOutlet;
CCnOutlet* pCnOutlet = new CCnOutletAdapter(pEnOutlet);
pCnOutlet->CnPlug();

delete pEnOutlet;
delete pCnOutlet;

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: