设计模式之适配器模式,以C++为例。

news2024/12/25 15:10:09

        今天来盘一盘适配器模式。适配器:顾名思义,就是让原本不合适的变为合适的,好似一对男女,没有中间的媒婆是不会互相了解的,好像不太恰当,就这么解释吧,只有有了这个中间人他们才会产生联系,进而相互了解、恋人、深入、结婚,咳咳,没有ghs哦,哈哈哈。

目录

一、适配器模式简介

二、C++适配器代码示例

三、图形编辑器中的适配器模式

四、与模版结合使用


本篇代码:

Thomas_Lbw / Cpp_Design_Patterns · GitCode

一、适配器模式简介

        适配器模式是一种设计模式,它允许一个类的接口适配另一个类的接口。适配器模式用于解决两个接口不兼容的问题。适配器将现有的类的接口包装在一个适配器类中,从而让这个现有类具有客户希望的接口。

适配器模式由以下三个组件组成:

  1. 目标接口:定义客户所需的接口。
  2. 需要适配的类:定义需要适配的类。
  3. 适配器类:适配器类实现了目标接口并继承了需要适配的类。

适配器模式常常用于以下场景:

  1. 当你需要使用一个已有的类,但它的接口不符合您的需求时。
  2. 当您想创建一个可以重复使用的类,该类可将不兼容的接口转换为客户希望的接口时。

适配器模式的优点:

  1. 可以让任何两个没有关联的类一起运行。
  2. 增加了类的透明性和复用性。
  3. 灵活性和可扩展性都非常好。

适配器模式主要应用在以下情况:

  1. 让两个不兼容的接口能够正常工作。
  2. 对一个已存在的类进行包装,使其具有其他接口,以便与其他类一起工作。
  3. 在不改变现有代码的情况下为一个类增加新的功能。
  4. 将一个类的接口转换为另一个客户希望的接口,以便使用现有的类。

        总结一下,适配器模式是一种很有用的设计模式,特别是在系统集成、复用现有类和代码重构等方面。

二、C++适配器代码示例

        假设我们有一个现有的类,该类具有一种特定的接口,但是我们需要使用它时需要它具有不同的接口。我们可以使用适配器模式解决这个问题。

#include <iostream>
#include <string>

// 目标接口
class Target {
 public:
  virtual void Request() = 0;
};

// 需要适配的类
class Adaptee {
 public:
  void SpecificRequest() {
    std::cout << "SpecificRequest of Adaptee." << std::endl;
  }
};

// 适配器类
class Adapter : public Target, private Adaptee {
 public:
  void Request() {
    SpecificRequest();
  }
};

int main() {
  Target* target = new Adapter();
  target->Request();
  return 0;
}

        适配器类Adapter继承了Target和Adaptee,将两个类中的方法柔和在一起,并且没有更改其代码,像不像媒婆?下面是代码类图:

三、图形编辑器中的适配器模式

        开发一个图形编辑器,并且你需要支持多种图形类型,如矩形、圆形和三角形。每种图形类型都具有自己的接口,但你需要统一接口来绘制所有类型的图形。

#include <iostream>

// 目标接口
class Shape {
 public:
  virtual void Draw() = 0;
};

// 矩形类
class Rectangle {
 public:
  void DrawRectangle() {
    std::cout << "Drawing Rectangle." << std::endl;
  }
};

// 圆形类
class Circle {
 public:
  void DrawCircle() {
    std::cout << "Drawing Circle." << std::endl;
  }
};

// 三角形类
class Triangle {
 public:
  void DrawTriangle() {
    std::cout << "Drawing Triangle." << std::endl;
  }
};

// 矩形适配器
class RectangleAdapter : public Shape, private Rectangle {
 public:
  void Draw() {
    DrawRectangle();
  }
};

// 圆形适配器
class CircleAdapter : public Shape, private Circle {
 public:
  void Draw() {
    DrawCircle();
  }
};

// 三角形适配器
class TriangleAdapter : public Shape, private Triangle {
 public:
  void Draw() {
    DrawTriangle();
  }
};

int main() {
  Shape* shapes[3];
  shapes[0] = new RectangleAdapter();
  shapes[1] = new CircleAdapter();
  shapes[2] = new TriangleAdapter();

  for (int i = 0; i < 3; i++)
    shapes[i]->Draw();

  return 0;
}

         我们定义了一个Shape接口,该接口定义了统一的接口来绘制所有图形。然后,我们定义了三个不同的图形类,每个类都有自的接口,但是与目标接口不同。接下来,我们定义了三个适配器类,分别对应矩形、圆形和三角形,每个适配器都继承了Shape接口,并私有继承了相应的图形类。这样,我们就可以使用适配器对象来访问原本不兼容的图形类,并且在不改变原有代码的情况下实现统一的接口。

        类图如下:

四、与模版结合使用

        C++ 适配器模式写法一般会使用模板来提高代码的可读性和灵活性。下面是一个简单的例子:

#include <iostream>

// 抽象图形接口
class Shape {
 public:
  virtual void Draw() = 0;
  virtual int GetX() const = 0;
  virtual int GetY() const = 0;
  virtual ~Shape() = default;
};

// 待适配的矩形类
class Rectangle {
 public:
  Rectangle(int x, int y) : x_(x), y_(y) {}
  void DrawShape() {
    std::cout << "Drawing rectangle at (" << x_ << ", " << y_ << ")\n";
  }
  int GetXCoordinate() const { return x_; }
  int GetYCoordinate() const { return y_; }
 private:
  int x_, y_;
};

// 适配器模板类
template <typename T>
class ShapeAdapter : public Shape {
 public:
  ShapeAdapter(T* adaptee) : adaptee_(adaptee) {}
  void Draw() override {
    adaptee_->DrawShape();
  }
  int GetX() const override {
    return adaptee_->GetXCoordinate();
  }
  int GetY() const override {
    return adaptee_->GetYCoordinate();
  }
 private:
  T* adaptee_;
};

int main() {
  Rectangle* rectangle = new Rectangle(10, 20);
  Shape* shape = new ShapeAdapter<Rectangle>(rectangle);
  shape->Draw();
  std::cout << "X: " << shape->GetX() << ", Y: " << shape->GetY() << '\n';
  delete shape;
  delete rectangle;
  return 0;
}

        这段代码中,我们定义了一个模板类ShapeAdapter,这个类接受一个类型参数,表示待适配的图形类。适配器类继承了抽象接口Shape,并实现了其中的三个方法。在实现中,适配器类通过私有成员变量adaptee_存储待适配的图形对象,并通过继承的接口方法调用相应的图形类方法。

        这种写法非常灵活,因为我们可以使用任意的图形类作为适配器的类型参数,并且可以很容易地扩展或替换适配器类的实现。而且,这种写法还易于维护,因为每个图形类的适配器都是独立的,不会影响其他图形类的适配器实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/192958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能驾驶开启高精定位新赛道,这家供应商正加码布局海外市场

高工智能汽车研究院监测数据显示&#xff0c;2022年1-11月中国市场乘用车前装标配搭载NOA交付达到18.38万辆&#xff0c;同比增长91.86%&#xff1b;同时&#xff0c;NOA搭载的车型配置价格还在不断下滑&#xff0c;正在把NOA的配置拉至15万元价格区间。 而作为高精定位&#x…

面向对象——static(静态)Math类自定义工具类代码块

目录 static&#xff08;静态&#xff09;关键字 static的注意事项 static的优点和缺点 应用场景 自定义工具类 代码块 static&#xff08;静态&#xff09;关键字 static是一个修饰符&#xff0c;用于修饰成员&#xff08;成员变量 、成员方法&#xff09;static的特点…

Redis处理client连接数过多,大量空闲链接无法释放问题

打开redis命令终端&#xff0c;输入&#xff1a; client list 查看连接数&#xff0c;用于返回所有连接到服务器的客户端信息和统计数据 参数解析&#xff1a; id: 唯一的64位的客户端ID(Redis 2.8.12加入)。 addr: 客户端的地址和端口 fd: 套接字所使用的文件描述符 age…

python真的很骚可惜你不会

python基本语法 &#x1f4d2;博客主页&#xff1a; 微笑的段嘉许博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐留言&#x1f4dd; &#x1f4cc;本文由微笑的段嘉许原创&#xff01; &#x1f4c6;51CTO首发时间&#xff1a;&#x1f334;2023年1月日3…

redis分布式缓存

文章目录一、redis持久化1.1.RDB持久化1.1.1.执行时机1.1.2.RDB原理1.1.3.小结1.2.AOF持久化1.2.1.AOF原理1.2.2.AOF配置1.2.3.AOF文件重写1.2.4.小结1.3.RDB与AOF对比二、Redis主从集群2.1.集群结构2.2.准备实例和配置2.3.启动2.4.开启主从关系2.5.测试2.6.主从数据同步原理2.…

Codeforces Round #848 (Div. 2) A-E 赛时思路+正解

青大蒟蒻第一次在正式的div2div2div2中AcAcAc了五道题&#xff0c;也是小蒟蒻有史以来发挥最好的一场&#xff0c;这场过后我的cf也许可能也要变成黄了。 A. Flip Flop Sum 题意&#xff1a;给定一个a——ia——ia——i数组&#xff0c;权值仅为1或-1&#xff0c;我们选择相邻…

《死亡空间》重制回归!无法启动怎么办?

作为科幻生存恐怖系列的经典之作&#xff0c;《死亡空间》在推出15年后再次回归&#xff0c;果然引发热潮。精美震撼的科幻场景&#xff0c;强烈的视觉画面&#xff0c;加上阴森的3D 音效&#xff0c;重制版提升了身临其境之感&#xff0c;完全是沉浸式恐怖体验&#xff0c;只能…

红外遥控数码管显示

红外遥控器实物图红外遥控器接口电路数码管接口电路红外遥控数码管显示程序源代码/**************************红外遥控数码管显示************************** * 单片机&#xff1a;51单片机* 开发环境&#xff1a;keil * 名称:红外遥控数码管显示 * 功能&#xff1a;遥控器红外…

C语言常量

常量是固定值&#xff0c;在程序执行期间不会改变。这些固定的值&#xff0c;又叫做字面量。常量可以是任何的基本数据类型&#xff0c;比如整数常量、浮点常量、字符常量&#xff0c;或字符串字面值&#xff0c;也有枚举常量。常量就像是常规的变量&#xff0c;只不过常量的值…

OpenMMLAB AI实战营第一课笔记

计算机视觉的发展 计算机视觉是什么 计算机视觉是一门让计算机学会"看"的学科&#xff0c;研究如何自动理解图像和视频中的内容 计算机视觉的发展 早期萌芽&#xff08;1960-1980&#xff09; 统计机器学习与模式识别(1990-2000) ImageNet 大型数据库(2006) 斯坦…

ocelot+consul治理服务

consulConsul 是HashiCorp公司推出的开源工具&#xff0c;用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案相比&#xff0c;Consul的方案更“一站式”&#xff0c;内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方…

程序员副业接单做私活避坑指南

这篇文章系统的分享了对接单做私活这件事情的思考&#xff0c;也给出一些干货建议。希望让大家少走一些弯路&#xff0c;不要被坑。 先说结论 不建议大家在接单这个事情上投入太大精力&#xff0c;如果你“贼心不改”&#xff0c;建议大家以比较随缘的方式对待这件事情。 再说…

Linux云主机配置

Linux云主机配置 推荐环境&#xff1a; Mac 阿里云主机Linux 阿里云主机Windows Xshell 阿里云主机&#xff08;选择使用&#xff09;Windows 虚拟机 阿里云主机 1.云主机配置 选择配置的过程中&#xff0c;请注意选择操作系统版本为Ubuntu 16.04 64位 或 Ubuntu 18.04 6…

多位大厂专家鼎力推荐,44个微服务架构设计模式pdf,程序员福利

前言 本文的目标是让架构师和程序员学会使用微服务架构成功开发应用程序。 本文不仅讨论了微服务架构的好处&#xff0c;还描述了它们的弊端。读者将掌握如何在使用单体架构和使用微服务架构之间做出正确的权衡。 谁应该阅读本文&#xff1f; 本文的重点是架构和开发&#…

前端vue2实现头部组件(自定义背景icon+抽屉式使用指南展示)

一、文章引导 #mermaid-svg-Sqlx5Ih7pUPfo8rw {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Sqlx5Ih7pUPfo8rw .error-icon{fill:#552222;}#mermaid-svg-Sqlx5Ih7pUPfo8rw .error-text{fill:#552222;stroke:#55222…

Python多态及用法详解

Python 是弱类型语言&#xff0c;其最明显的特征是在使用变量时&#xff0c;无需为其指定具体的数据类型。这会导致一种情况&#xff0c;即同一变量可能会被先后赋值不同的类对象&#xff0c;例如&#xff1a;class CLanguage: defsay(self): print("赋值的是 CLanguage 类…

ElasticSearch从入门到出门【下】

文章目录数据聚合聚合的种类DSL实现聚合Bucket聚合语法聚合结果排序限定聚合范围Metric聚合语法RestAPI实现聚合API语法业务需求业务实现自动补全拼音分词器自定义分词器自动补全查询实现酒店搜索框自动补全修改酒店映射结构修改HotelDoc实体重新导入自动补全查询的JavaAPI实现…

阿里云领取免费2H2G云服务器&证书分享&个税抵扣:Apsara Clouder云计算专项技能认证:云服务器ECS入门

这个证书是你领服务器一个月内要考的&#xff0c;内容也不难。下面是90分左右的答案&#xff08;粗体&#xff09;&#xff0c;仅供参考……单选1&#xff0e;云服务器ECS以服务化的方式对客户提供&#xff0c;阿里云产品售后支持的时间段是&#xff1f;A.5*8B.7*8C.7*12D.7*24…

《MySQL高级篇》十四、多版本并发控制

文章目录1. 什么是MVCC2. 快照读与当前读2.1 快照读2.2 当前读3. 复习3.1 再谈隔离级别3.2 隐藏字段、Undo Log版本链4. MVCC实现原理之ReadView4.1 什么是ReadView4.2 设计思路4.3 ReadView的规则4.4 MVCC整体操作流程5. 举例说明5.1 READ COMMITTED隔离级别下5.2 REPEATABLE …

Gerrit3.4.1安装+its插件

环境依赖jdk11安装jdk11&#xff1a;下载&#xff1a; wget https://download.java.net/openjdk/jdk11/ri/openjdk-1128_linux-x64_bin.tar.gz解压&#xff1a; tar zxvf openjdk-1128_linux-x64_bin.tar.gzsudo update-alternatives --install /usr/bin/java java /home/jenki…