设计模式之适配器模式(C++)

简介: 设计模式之适配器模式(C++)

一、适配器模式是什么?

      适配器模式是一种结构型的软件设计模式,也称包装模式,即将相对复杂的功能(可能用到多个类)封装起来,提供一个使用者想要的接口,使用者只需要调用接口,不需要知道接口里封装的内容是如何实现的。


      个人工作中经常能用到适配器模式,比如在面对一些第三方库或者SDK开发时,它们的接口往往与我们自己想要的接口不一致,此时适配器模式可以很好地扮演一个接口转换器的角色,将别人的接口与我们的接口对应上。


      适配器模式的优点:

  1. 良好封装性。接口内的内容对使用者而言是透明的,即看不见,这确保了内部功能具备较好的封装性,不易被改动。
  2. 解耦。不匹配的两方在适配器的作用下可以做到解耦,不需要修改任何一方原有代码逻辑。
  3. 良好复用性。适配的两方不需要做任何修改,业务的实现可以通过适配器来完成,不同的业务可以使用不同的适配器。
  4. 良好扩展性。若要增加业务场景,只需要增加适配器类,来满足业务即可。

适配器模式的缺点:

  1. 不利于维护。因为业务的实现基于适配器完成,适配器中代码的复杂程度会越来越高,不熟悉业务或者底层逻辑的人难以短时间内接手维护。
  2. 系统结构易混乱。当业务量快速增加时,适配器类的数量也会快速增加,没有良好的系统架构布局,最终会使得整个系统臃肿且危险。

      适配器模式一般分为类适配器模式和对象适配器模式。

1)类适配器模式:适配器类通过继承适配者类(多重继承),达到适配目的,部分语言可能不支持多重继承(如C#)。

2)对象适配器模式:适配器类中存放适配者类的实例对象,调用它来达到适配目的,该模式较常用。



二、类适配器模式

2.1 结构图

      客户端即Main主函数,接口类给客户调用,适配者类是要被重新封装的功能类。在类适配器模式中,适配器类继承于接口类和适配者类,并在类中进行相关封装操作,使接口兼容。

2.2 代码示例

      场景描述:我准备调用一款巴斯勒相机进行相关工作,但是其SDK的接口与我希望的接口不太一样,为此我设计了一个适配器类,对巴斯勒第三方库进行再次封装,以使接口符合我的要求。

//BaslerCamera.h
/****************************************************/
#pragma once
#include <iostream>
using namespace std;
// 巴斯勒相机类(适配者)
class BaslerCamera
{
public:
  // 打开相机
  void openBaslerCamera() {
    cout << "巴斯勒相机:打开相机。" << endl;
  }
  // 关闭相机
  void closeBaslerCamera() {
    cout << "巴斯勒相机:关闭相机。" << endl;
  }
  // 打开曝光设置
  void openExposureSettings() {
    cout << "巴斯勒相机:打开曝光设置。" << endl;
  }
  // 更改相机帧率
  void changeCameraFrame() {
    cout << "巴斯勒相机:更改相机帧率。" << endl;
  }
};
//Camera.h
/****************************************************/
#pragma once
#include <iostream>
#include "BaslerCamera.h"
using namespace std;
// 相机接口类
class Camera
{
public:
  // 构造函数
  Camera() {};
  // 析构函数
  virtual ~Camera() {};
  // 打开相机
  virtual void openCamera() = 0;
  // 关闭相机
  virtual void closeCamera() = 0;
  // 配置属性
  virtual void setConfig() = 0;
};
// 相机适配器类
class CameraAdapter :public Camera, public BaslerCamera
{
public:
  // 打开相机
  virtual void openCamera() {
    openBaslerCamera();
  }
  // 关闭相机
  virtual void closeCamera() {
    closeBaslerCamera();
  }
  // 配置属性
  virtual void setConfig() {
    // 打开曝光设置
    openExposureSettings();
    // 更改相机帧率
    changeCameraFrame();
  }
};
//main.cpp
/****************************************************/
#include <iostream>
#include <string>
#include "Camera.h"
using namespace std;
int main()
{
  Camera *m_camera = new CameraAdapter();
  // 打开相机
  m_camera->openCamera();
  // 配置相机
  m_camera->setConfig();
  // 关闭相机
  m_camera->closeCamera();
  delete m_camera;
  return 0;
}

     程序结果如下。

      在上述示例中,我们可以看到,巴斯勒相机的相关功能被我进行了再次封装,我只需要通过继承了接口类的适配器类,调用相关的接口即可完成我要的功能,至于接口中如何调用巴斯勒的库,那就是接口开发者的工作了。

三、对象适配器模式

3.1 结构图

      对象适配器模式和类适配器模式相比,更适合大型项目的开发。在该模式中,适配器只需要继承接口类即可,而适配者以实例对象的形式存放在适配器类中,适配器通过调用对象的相关功能,同样可以达到封装效果。

3.2 代码示例

      场景描述:与类适配器模式一致。

//Camera.h
/****************************************************/
#pragma once
#include <iostream>
#include "BaslerCamera.h"
using namespace std;
// 相机接口类
class Camera
{
public:
  // 构造函数
  Camera() {};
  // 析构函数
  virtual ~Camera() {};
  // 打开相机
  virtual void openCamera() = 0;
  // 关闭相机
  virtual void closeCamera() = 0;
  // 配置属性
  virtual void setConfig() = 0;
};
// 相机适配器类
class CameraAdapter :public Camera
{
public:
  // 构造函数
  CameraAdapter() {
    m_baslerCamera = new BaslerCamera();
  }
  // 析构函数
  virtual ~CameraAdapter() {
    if (m_baslerCamera != nullptr) {
      delete m_baslerCamera;
      m_baslerCamera = nullptr;
    }
  }
  // 打开相机
  virtual void openCamera() {
    m_baslerCamera->openBaslerCamera();
  }
  // 关闭相机
  virtual void closeCamera() {
    m_baslerCamera->closeBaslerCamera();
  }
  // 配置属性
  virtual void setConfig() {
    // 打开曝光设置
    m_baslerCamera->openExposureSettings();
    // 更改相机帧率
    m_baslerCamera->changeCameraFrame();
  }
private:
  BaslerCamera *m_baslerCamera;                 // 适配者类实例
};

      适配器类做了改变,类中增加了一个适配者类的实例对象,调用的结果同类适配器模式一致,就不再展示了。

四、总结

      我尽可能用较通俗的话语和直观的代码例程,来表述我对适配器模式的理解,或许有考虑不周到的地方,如果你有不同看法欢迎评论区交流!希望我举的例子能帮助你更好地理解适配器模式。

      如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

相关文章
|
3天前
|
设计模式 JSON 前端开发
前端必须掌握的设计模式——适配器模式
适配器模式是一种结构型设计模式,用于使接口不兼容的对象能够相互合作。通过在客户端和系统之间引入一个“中间层”适配器,将不同类型的输入数据转换为系统能处理的标准格式,减轻系统的负担,提高扩展性和可维护性。例如,MacBook的扩展坞将多种接口(如HDMI、USB)转换为Type-C接口,实现多接口兼容。
|
3月前
|
设计模式 Java 程序员
Java设计模式-适配器模式(8)
Java设计模式-适配器模式(8)
|
7月前
|
设计模式 Java
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
|
2月前
|
设计模式 Java
Java设计模式之适配器模式
这篇文章详细讲解了Java设计模式中的适配器模式,包括其应用场景、实现方式及代码示例。
56 0
|
3月前
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
4月前
|
设计模式 XML 存储
【六】设计模式~~~结构型模式~~~适配器模式(Java)
文章详细介绍了适配器模式(Adapter Pattern),这是一种结构型设计模式,用于将一个类的接口转换成客户期望的另一个接口,使原本不兼容的接口能够一起工作,提高了类的复用性和系统的灵活性。通过对象适配器和类适配器两种实现方式,展示了适配器模式的代码应用,并讨论了其优点、缺点以及适用场景。
|
5月前
|
设计模式 C++
C++一分钟之-设计模式:工厂模式与抽象工厂
【7月更文挑战第14天】设计模式是解决软件设计问题的通用方案。工厂模式与抽象工厂模式是创建型模式,用于对象创建而不暴露创建逻辑。工厂模式推迟实例化到子类,但过度使用会增加复杂性。抽象工厂则创建相关对象族,但过度抽象可能造成不必要的复杂度。两者均应按需使用,确保设计灵活性。代码示例展示了C++中如何实现这两种模式。
48 3
|
5月前
|
设计模式 安全 C++
C++一分钟之-C++中的设计模式:单例模式
【7月更文挑战第13天】单例模式确保类只有一个实例,提供全局访问。C++中的实现涉及线程安全和生命周期管理。基础实现使用静态成员,但在多线程环境下可能导致多个实例。为解决此问题,采用双重检查锁定和`std::mutex`保证安全。使用`std::unique_ptr`管理生命周期,防止析构异常和内存泄漏。理解和正确应用单例模式能提升软件的效率与可维护性。
67 2
|
6月前
|
设计模式
适配器模式-大话设计模式
适配器模式-大话设计模式
|
5月前
|
设计模式 Go 数据处理
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式