C++设计模式:适配器模式(十四)

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做的实现,这就是一种适配器。

      cpp 复制代码
      template<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());
相关推荐
wuyk5554 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无5 小时前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
波特率1152005 小时前
C++新特性---属性说明符与标准属性
开发语言·c++
不会代码的小猴5 小时前
3. 控件学习1
开发语言·c++·笔记·qt·算法
烧酒同学10 小时前
【C++】记录size of std::vector的巧妙坑
开发语言·c++·图形渲染
@呱呱爱学习12 小时前
C++大成之路_ STL容器_ Vector
开发语言·c++
码匠许师傅13 小时前
【C++ 面试真题】19. 聊聊 C++ 的迭代器
开发语言·c++·面试
qeen8713 小时前
【数据结构】红黑树的算法原理解析与实现
开发语言·数据结构·c++·算法·红黑树
码匠许师傅13 小时前
【C++ 面试真题】20. 聊聊 C++ 的标准库常用算法
c++·算法·面试
AI人工智能+电脑小能手13 小时前
大白话说Java设计模式-23-桥接模式(源码剖析篇)
java·设计模式·jdbc·桥接模式·源码分析·awt·java logging