适配器模式(Adapter Pattern)
意图:
将目标类型的接口转换为客户期望的接口,从而使接口不兼容的类一起协作
应用场景:
- 当某个已存在类提供的接口不是客户端期望的接口
- 当想在不必提供兼容接口的客户类中重用目标类
- 接口转换
影响
- 适配器静态绑定到被适配对象,无法重新适配其他目标对象
参与者
Client 、 Target 、 Adaptee 、Adapter
例:
在Cos系统中,MView类显示菜单列表MList时,使用数据结构类型为List<HashMap<String,String> >,
而数据源对象类MDate只提供Cursor数据结构。
public class MAdapter{
MData data;
public List<HashMap<String,String> > getData(){
Cursor c data.getData();
//转换为List<HashMap<String,String> >
//....
return List<HashMap<String,String> >;
}
}
public class MView{
void method(){
Mlist view = new MAdapter();
view.getData();
//...
}
}
C++:
目标接口(新街口):
//目标接口(新接口)
class ITarget {
public:
virtual void process() = 0;
};
遗留接口(老接口):
//遗留接口(老接口)
class IAdaptee {
public:
virtual void foo(int data) = 0;
virtual int bar() = 0;
};
遗留类型(实现的老接口):
class OldClass :public IAdaptee{
//***
public:
virtual void foo(int data) {}
virtual int bar() {}
};
对象适配器Adapter:
class Adapter : public ITarget {
protected:
IAdaptee* pAdaptee; //组合
public:
Adapter(IAdaptee* pAdaptee) {
this->pAdaptee = pAdaptee;
}
virtual void process() {
int data = pAdaptee->bar();
pAdaptee->foo(data);
}
};
实现:
int main() {
IAdaptee* pAdaptee = new OldClass(); //旧的类
//旧的类,在新的接口中去实现
ITarget* pTarget = new Adapter(pAdaptee); //在新的类接口中实现中实现
pTarget->process();
return 0;
}
总结
- Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一直的情况”,在遗留代码复用、类的迁移等方面非常有用
- 一般用两种Adapter的现象方式。类适配器采用“多继承”的实现方式,一般不推荐使用,一般采用“对象组合”的方式,更符合松耦合精神
- Adapter模式实现很灵活,不必拘束于GoF定义的两种结构。
例如:将Adapter模式中的“现存对象”作为新的接口参数,来达到适配的目的。