参考连接:
http://www.cnblogs.com/jiese/p/3166396.html
http://www.cnblogs.com/onlycxue/p/3476932.html
http://www.jb51.net/article/55872.htm
为什么要使用适配器模式?
在软件开发中,有的时候系统的数据和行为都正确,但接口不符合,我们应该考虑使用适配器模式,目的是使控制范围之外的一个原有对象与某个接口匹配。举个例子:在开发一个模块的时候,有一个功能点实现起来比较费劲,但是,之前有一个项目的模块实现了一样的功能点;但是现在这个模块的接口和之前的那个模块的接口是不一致的。此时,作为项目经理的你,该怎么办啦?当然是在中间加一层Wrapper了,也就是使用适配器模式,将之前实现的功能点适配进新的项目了。为什么呢?主要是使用适配器模式有以下优点:
1.降低了去实现一个功能点的难度,可以对现有的类进行包装,就可以进行使用了;
2.提高了项目质量,现有的类一般都是经过测试的,使用了适配器模式之后,不需要对旧的类进行全面的覆盖测试;
3.总的来说,提高了效率,降低了成本。
什么时候使用适配器模式?
每一种设计模式都有它最适用的场合。适配器模式在以下场合下最适用:
使用一个已经存在的类,如果它的接口和你实际要求的不一致时,可以考虑使用适配器模式;要在调用者和功能提供者双方都不太容易修改的时候再使用适配器模式,而不是一有不同时就使用它。
Adatper作用:
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。系统的数据和行为都正确,但接口不符时,我们应该考虑使用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。
比如购买的第三方开发组件,该组件接口与我们自己系统的接口不相同,或者由于某种原因无法直接调用该组件,可以考虑适配器。
Adatper分类:类适配器模式、对象适配器模式
1.类适配器模式UML类图:
2.对象配器模式UML类图:
3.类适配器模式代码:
Adatper.h代码:
#ifndef _ADAPTER_H_
#define _ADAPTER_H_
#include <iostream>
using namespace std;
class Target //用户访问的对象
{
public:
Target(){}
virtual ~Target(){}
virtual void Request(){ cout << "Target Request..." << endl; }
private:
};
class Adaptee //需要适配的对象
{
public:
Adaptee(){}
virtual ~Adaptee(){}
void SpecificRequest(){ cout << "Adaptee SpecificRequest..." << endl; }
private:
};
//1.类适配器 ,通过private继承,获得父类方法SpecificRequest()实现父类方法:Request()
class ClassAdapter :public Target, private Adaptee
{
public:
ClassAdapter(){}
virtual ~ClassAdapter(){}
virtual void Request() // 实现父类方法:Request()
{
cout << "ClassAdapter Request..." << endl;
this->SpecificRequest();//调用父类方法:SpecificRequest()
}
private:
};
#endif
客户端代码:
Target *pTarget = new ClassAdapter();
pTarget->Request();
if (pTarget)
{
delete pTarget;
pTarget = nullptr;
}
输出:
ClassAdapter Request...
Adaptee SpecificRequest...
请按任意键继续. . .
4.对象配器模式代码:
Adatper.h代码:
#ifndef _ADAPTER_H_
#define _ADAPTER_H_
#include <iostream>
using namespace std;
class Target //用户访问的对象
{
public:
Target(){}
virtual ~Target(){}
virtual void Request(){ cout << "Target Request..." << endl; }
private:
};
class Adaptee //需要适配的对象
{
public:
Adaptee(){}
virtual ~Adaptee(){}
void SpecificRequest(){ cout << "Adaptee SpecificRequest..." << endl; }
private:
};
//2.对象适配器 ,只继承Target,没有继承Adaptee
class ClassAdapter :public Target
{
public:
ClassAdapter(){ m_pAdaptee = new Adaptee(); }
ClassAdapter(Adaptee* pAdaptee){ m_pAdaptee = pAdaptee; }
virtual ~ClassAdapter(){}
virtual void Request() // 实现父类方法:Request()
{
cout << "ClassAdapter Request..." << endl;
this->m_pAdaptee->SpecificRequest();//调用m_pAdaptee对象方法:SpecificRequest()
}
private:
Adaptee* m_pAdaptee;
};
#endif
客户端代码:
//调用方法1:默认构造函数
Target *pTarget = new ClassAdapter();
pTarget->Request();
if (pTarget)
{
delete pTarget;
pTarget = nullptr;
}
cout << endl;
//调用方法2:传入Adaptee对象的构造函数
Adaptee* pAdaptee = new Adaptee();
Target *pTarget2 = new ClassAdapter(pAdaptee);
pTarget2->Request();
if (pTarget2)
{
delete pTarget2;
pTarget2 = nullptr;
}
if (pAdaptee)
{
delete pAdaptee;
pAdaptee = nullptr;
}
输出:
ClassAdapter Request...
Adaptee SpecificRequest...
ClassAdapter Request...
Adaptee SpecificRequest...
请按任意键继续. . .
扩展知识【接口继承与实现继承】:
在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。
接口继承和实现继承是面向对象领域的两个重要的概念。
接口继承指的是通过继承,子类获得了父类的接口。通过纯抽象基类模拟接口继承的效果。(但是在C++中pure virtual function也可以提供默认实现,因此这是不纯正的接口继承)
实现继承指的是通过继承子类获得了父类的实现(并不通过接口)。我们可以通过private继承获得实现继承的效果(private继承后,父类中的接口都变为private,当然只能是实现继承了。)
在C++中的public继承既是接口继承又是实现继承,因为子类在继承了父类后既可以对外提供父类中的接口操作,又可以获得父类的接口实现。