1、定义与动机
-
定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。
-
动机:
- 在软件系统中,由于应用环境的变化,常常需要将"一些现存的对象"放在新的环境中应用,但新环境要求的接口是这些现存对象所不满足的。
- 如何应对这种"迁移的变化"?如何既能利用现有对象的良好视线同时又能满足心得应用环境所要求的接口?
-
个人理解:适配器模式很常见也非常有用,生活中到处都是适配,电脑VGA和HDMI转接口、水管弯头、变压器是不是也可以认为是一种适配器...它主要是为了解决已有物体与现在需求物不匹配的一个情况,进行一层封装(转接口、弯头)以达到复用的效果
2、实现代码
-
适配器模式的代码并没有一个统一的标准,其主要体现在加一层封装调用老接口的一种形式
-
当出现老接口与目标接口不匹配时,此时适配器模式就可以很好的适用进来。
cpp
// 老接口
class IAdaptee {
public:
virtual void foo(int data) = 0;
virtual int bar() = 0;
};
class Adaptee:public IAdaptee {
public:
virtual void foo(int data) override{
}
virtual int bar() override{
}
};
// 目标接口
class ITarget{
public:
virtual void process() = 0;
};
class Adapter: public IAdaptee{
private:
IAdaptee* adaptee; // 多态
public:
Adapter(IAdaptee *iAdaptee): adaptee(iAdaptee){
}
virtual void process() override{
// ...
int data = adaptee->bar();
adaptee->foo(data);
// ...
}
};
3、总结
-
Adapter模式主要应用于"希望复用一些现存的类,但是接口又与复用环境要求不一致的情况",在遗留代码复用、类库迁移等方面非常有用
-
GoF 23定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用"多继承"的实现方式,一般不推荐使用。对象适配器采用"对象组合"的方式,更符合松耦合精神。
cpp// 多继承, 类适配器 高耦合,并且无法动态的适应老接口(老接口可能存在多个) class Adapter: public IAdaptee, private IAdaptee { };
-
Adapter模式可以实现的非常灵活,不必拘泥于GoF 23中定义的两种接口。例如,完全可以将Adapter模式中的"现存对象"作为新的接口方法参数,来达到适配的目的。
-
适用场景:老接口与目标接口不匹配时,用于解决一个兼容性问题
-
STL中stack栈和queue队列都是基于一个deque做的实现,这就是一种适配器。
cpptemplate<typename _Tp, typename _Sequence = deque<_Tp> > class queue; template<typename _Tp, typename _Sequence = deque<_Tp> > class stack
-
SpringMVC Framework中在解析Web请求的参数时也会存在多种适配器用于解析不同类型的参数,但它们都是通过一个HandlerAdapter的接口来进行选择调用具体的适配器来适配解析参数
java// 找到处理器的适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { private List<HandlerAdapter> handlerAdapters; if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } } // 获取参数、执行controller mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
-