在上面生活中问题的解决方式也就正好对应了Adapter模式的两种类别:类模式和对象模式。
Adapter模式典型的结构图为:
Adapter Pattern(类模式)结构图
Adapter Pattern(对象模式)结构图
在Adapter模式的结构图中可以看到,类模式的Adapter采用继承的方式复用Adaptee的接口,而在对象模式的Adapter中我们则采用组合的方式实现Adaptee的复用。有关这些具体的实现和分析将在代码说明和讨论中给出。
类模式的Adapter实现:
//Adapter.h
#ifndef _ADAPTER_H_
#define _ADAPTER_H_
class Target
{
public:
Target();
virtual ~Target();
virtual void Request();
protected:
private:
};
class Adaptee
{
public:
Adaptee();
~Adaptee();
void SpecificRequest();
protected:
private:
};
class Adapter:public Target,private Adaptee
{
public:
Adapter();
~Adapter();
void Request();
protected:
private:
};
#endif //~_ADAPTER_H_
代码片断2:Adapter.cpp
//Adapter.cpp
#include "Adapter.h"
#include <iostream>
Target::Target()
{
}
Target::~Target()
{
}
void Target::Request()
{
std::cout<<"Target::Request"<<std::endl;
}
Adaptee::Adaptee()
{
}
Adaptee::~Adaptee()
{
}
void Adaptee::SpecificRequest()
{
std::cout<<"Adaptee::SpecificRequest"<<std::endl;
}
Adapter::Adapter()
{
}
Adapter::~Adapter()
{
}
void Adapter::Request()
{
this->SpecificRequest();
}
代码片断1:Adapter.h
//Adapter.h
#ifndef _ADAPTER_H_
#define _ADAPTER_H_
class Target
{
public:
Target();
virtual ~Target();
virtual void Request();
protected:
private:
};
class Adaptee
{
public:
Adaptee();
~Adaptee();
void SpecificRequest();
protected:
private:
};
class Adapter:public Target
{
public:
Adapter(Adaptee* ade);
~Adapter();
void Request();
protected:
private:
Adaptee* _ade;
};
#endif //~_ADAPTER_H_
代码片断2:Adapter.cpp
//Adapter.cpp
#include "Adapter.h"
#include <iostream>
Target::Target()
{
}
Target::~Target()
{
}
void Target::Request()
{
std::cout<<"Target::Request"<<std::endl;
}
Adaptee::Adaptee()
{
}
Adaptee::~Adaptee()
{
}
void Adaptee::SpecificRequest()
{
std::cout<<"Adaptee::SpecificRequest"<<std::endl;
}
Adapter::Adapter(Adaptee* ade)
{
this->_ade= ade;
}
Adapter::~Adapter()
{
}
void Adapter::Request()
{
_ade->SpecificRequest();
}
第
代码片断3:main.cpp
//main.cpp
#include "Adapter.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
Adaptee* ade = new Adaptee;
Target* adt = new Adapter(ade);
adt->Request();
return 0;
}
Adapter模式实现上比较简单,要说明的是在类模式Adapter中,我们通过private继承Adaptee获得实现继承的效果,而通过public继承Target获得接口继承的效果。
在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承,子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不统共接口)。在C++中的public继承既是接口继承又是实现继承,因为子类在继承了父类后既可以对外提供父类中的接口操作,又可以获得父类的接口实现。当然我们可以通过一定的方式和技术模拟单独的接口继承和实现继承,例如我们可以通过private继承获得实现继承的效果(private继承后,父类中的接口都变为private,当然只能是实现继承了。),通过纯抽象基类模拟接口继承的效果,但是在C++中pure virtual function也可以提供默认实现,因此这是不纯正的接口继承,但是在Java中我们可以interface来获得真正的接口继承了。
以上是c++方面的内容,java由于其独有的接口特性在adapter的设计上又有稍微的不同
为复用而设计的通用的类,总是存在一些特殊的情况,使其不能够使用或者完成相应的扩展性的功能。
看文中所给的例子:绘图编辑器中新增加文本图形编辑
TextView是呈现文本的,并不支持图形编辑的方式,新增加TextShape,是无法直接使用TextView中的方法,
但同时还要存在Shape的操作,或许还要新增加特性或者操作,这些都要求必须要新增加一个类来完成这些功能。
为了能够使用到TextView中已经存在对于文本的处理方法,就需要继承TextView或者组合TextView对象。
适用性和结构
使用一个已经存在的类,但是接口不符合要求
创建一个可以复用的类,与其他不相关的类协同工作
对象适配器适配父类接口
继承方式——类适配器:
组合方式——对象适配器:
继承和组合这两种方式还是有些区别的,需要权衡:
1 类适配器
只能保证Adapter所匹配的基类Adaptee是能够胜任的,对于Adaptee基类所派生下来的子类不一定能够完全胜任。
Adapter能够重新定义基类的方法和扩展自己的方法
仅仅引入一个对象,并不需要额外指针以间接得到Adaptee。
2 对象适配器
一个Adapter可以对应Adaptee本身及其子类
能够进行扩展,但如果对于基类本身及其子类修改该比较麻烦的
3 深度探索
Adapter的匹配程度工作量,取决于Target和Adaptee相似程度
可插入的适配器:能将适配器运用到系统中
双向匹配器:与被匹配的类都兼容,都可以工作。
实现
1实现颜色亮度可变灯:
有一盏灯其颜色可变,但是现在要求其明亮度也可变,明亮度是由电压和颜色共同决定的。需要一个适配器来完成这个工作。
//电压转换器
class VoltageConveter
{
public:
VoltageConveter(){cout<<" VoltageConveter constructor "<<endl;}
void bindInputVoltage(int voltage){}
void adjustVoltage(int rate){}
private:
int m_voltage;
};
//彩色灯
class ColourLight
{
public:
ColourLight(){cout<<" ColourLight constructor "<<endl;}
void setColorType(int color){}
private:
int m_colorType;
};
//类适配器
class BrightAdapter: public ColourLight,public VoltageConveter
{
public:
BrightAdapter(){cout<<" BrightAdapter constructor "<<endl;}
void setLightness(){}
int getLightness(){}
private:
int m_lightness;
};
2 手机上的文本编辑框控件实现
其中包括两个部分:文本显示和输入法。文本显示不是专为编辑框服务,输入法也并不为编辑框。
所以要将文本显示和输入法结合起来才能实现文本编辑框。同时文本编辑框又需要添加自己的特性,以及配合输入法的使用。
大概的结构图如下: