当前位置: 首页 > news >正文

Adapter适配器模式

Adapter适配器模式是一种结构设计模式,用于解决接口不兼容的问题,通过适配器类,可以将一个类的接口转换为客户渴望的另一个接口,从而使原来无法协作的对象能够一起工作。

角色和职责:
目标接口(Target):定义客户希望使用的接口。
被适配者(Adaptee):需要适配的类或接口,其方法不符合客户的需求。
适配器(Adapter):实现目标接口

优点:
复用性:可以在不修改原有代码的情况下复用现有类。
灵活性:通过适配器,可以轻松支持新的接口或类。
符合开闭原则:扩展功能时,无需修改原有代码,只需增加新的适配器类。

缺点:
复杂性:增加了系统的复杂性,需要维护适配器类。
性能开销:适配器类可能会引入额外的性能开销。

应用场景:
第三方库集成:当需要使用第三方库但其接口不符合项目需求时,可以使用适配器模式。
旧系统改造:在改造旧系统时,可以使用适配器模式将旧接口适配为新接口。
不同数据库适配:在需要使用不同数据库时,可以通过适配器模式统一接口。

适配器模式从实现方式上可以分为两种:类适配器和对象适配器。它们的区别主要在于实现方法和适用情况的不同。

类适配器

定义:类适配器通过继承被适配类(Adaptee)并实现目标接口(Target)来实现适配。它利用继承关系,将被适配类的接口转换为目标接口。

实现方式:
适配器类直接继承被适配类。
适配器类实现目标接口,并重写目标接口中的方法,将调用转换为被适配类的方法调用。

优点:
直接继承被适配类,复用性强。
可以重定义被适配类的部分行为。

缺点:
由于继承关系,适配器类与被适配类之间耦合度较高,难以处理被适配类的子类。
不支持多个被适配类的适配,因为一个类只能继承一个父类。

适用场景:
需要复用被适配类的部分实现。
被适配类没有子类,或者适配器不需要处理被适配类的子类。

对象适配器

定义:对象适配器通过组合的方式,将被适配类(Adaptee)作为成员变量,并实现目标接口(Target)。它利用对象组合关系,动态地将被适配类的接口转换为目标接口。

实现方式:
适配器类包含一个被适配类的引用。
适配器类实现目标接口,并重写目标接口中的方法,将调用委托给被适配类的方法。

优点:
灵活性高,可以适配多个不同的被适配类。
支持被适配类及其子类的适配,因为组合关系不依赖于继承。
符合“合成复用原则”,即优先使用组合而不是继承。

缺点:
需要引入额外的引用,可能增加系统复杂性。
重定义被适配类的行为较为困难,需要定义被适配类的子类。

适用场景:
需要适配多个不同的被适配类。
被适配类有子类,且适配器需要处理这些子类。

在这里插入图片描述

类适配器模式

// 目标接口
class Target {
public:// 纯虚函数,模拟 Java 接口的抽象方法virtual void request() = 0;// 虚析构函数,确保正确释放派生类对象virtual ~Target() {}
};// 被适配类
class Adaptee {
public:void specificRequest() {std::cout << "特殊请求" << std::endl;}
};// 类适配器:继承Adaptee并实现Target接口
class ClassAdapter : public Adaptee, public Target {
public:// 实现Target接口的request方法void request() override {specificRequest();}
};

对象适配器模式

// 目标接口
class Target {
public:// 纯虚函数,模拟 Java 接口的抽象方法virtual void request() = 0;// 虚析构函数,确保正确释放派生类对象virtual ~Target() {}
};// 被适配类
class Adaptee {
public:void specificRequest() {std::cout << "特殊请求" << std::endl;}
};// 对象适配器:组合Adaptee并实现Target接口
class ObjectAdapter : public Target {
private:Adaptee* adaptee;
public:ObjectAdapter(Adaptee* adaptee) : adaptee(adaptee) {}// 实现Target接口的request方法void request() override {adaptee->specificRequest();}// 析构函数~ObjectAdapter() {// 这里不删除 adaptee,因为它可能由外部管理}
};

相关文章:

  • 利用systemd启动部署在服务器上的web应用
  • Zookeeper入门(三)
  • node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
  • 从零开始实现大语言模型(十六):加载开源大语言模型参数
  • Flink 并行度的设置
  • 给个人程序加上MCP翅膀
  • 基于labview的声音采集、存储、处理
  • GitHub 趋势日报 (2025年05月17日)
  • C++(243~263)STL常用算法、遍历算法(for_each,Transform)、查找算法、拷贝和替换、常用算术生成,常用集合算法。
  • C++学习:六个月从基础到就业——C++17:if/switch初始化语句
  • 【随机过程】贝叶斯估计
  • 【计算机网络】第一章:计算机网络体系结构
  • TIMER免疫浸润分析
  • 轻量级视频剪辑方案:FFmpeg图形化工具体验
  • 国内人工智能行业研究报告 投资要点
  • Spring Cloud 技术实战
  • 非线性1 修改
  • 23种设计模式解释+记忆
  • 5.18本日总结
  • VMware虚拟机磁盘扩容与LVM分区操作指南
  • 多个“首次”!上市公司重大资产重组新规落地
  • 关税互降后的外贸企业:之前暂停的订单加紧发货,后续订单考验沟通谈判能力
  • 泽连斯基已离开土耳其安卡拉
  • 佩斯科夫:俄方代表团15日将在伊斯坦布尔等候乌克兰代表团
  • 5吨煤炭“瞬间蒸发”?掺水炭致企业损失千万,腐败窝案曝光
  • 沙青青评《通勤梦魇》︱“人机组合”的通勤之路