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());
相关推荐
煤泥做不到的!39 分钟前
挑战一个月基本掌握C++(第十一天)进阶文件,异常处理,动态内存
开发语言·c++
F-2H42 分钟前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
axxy20001 小时前
leetcode之hot100---24两两交换链表中的节点(C++)
c++·leetcode·链表
若亦_Royi2 小时前
C++ 的大括号的用法合集
开发语言·c++
ragnwang6 小时前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
lqqjuly9 小时前
特殊的“Undefined Reference xxx“编译错误
c语言·c++
冰红茶兑滴水9 小时前
云备份项目--工具类编写
linux·c++
刘好念9 小时前
[OpenGL]使用 Compute Shader 实现矩阵点乘
c++·计算机图形学·opengl·glsl
酒鬼猿10 小时前
C++进阶(二)--面向对象--继承
java·开发语言·c++
姚先生9710 小时前
LeetCode 209. 长度最小的子数组 (C++实现)
c++·算法·leetcode