【设计模式】适配器模式

news/2024/11/26 23:17:39/

一,定义

适配器模式:结构型模式之一,适配器提供客户类需要的接口,适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器可以使由于接口不兼容而不能交互的类可以一起工作。

适配器模式分为两种:

  • 类适配器(适配器和适配者是继承关系

  • 对象适配器(适配器和适配者是关联关系

二,类图

三,成员职责

  • 抽象目标角色:目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。

  • 适配者角色:适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心

在类适配器中,它通过继承Target和Adaptee使二者产生联系

在对象适配器中,它通过继承Target并关联一个Adaptee对象(设置为私有成员)使二者产生联系。

  • 适配器角色:适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法。

四,实现

我们给出以下场景:

现在有两种规格的插座:中式规格插座和英式规格插座,我们现在不改变英国插座的基础,使英国可以转化为中国插座的规格

英国插座(抽象目标类Target)

class uksoket_target
{
public:virtual void ukplug(){cout << "英国插座:英式规格" << endl;}
};

中国插座(适配者类Adaptee)

class chsoket_adaptee  //适配者
{
public:void chplug(){cout << "中式规格" << endl;}
};
  1. 类适配器

英式插座适配器(适配器类Adapter)

class uksocket_adapter : public uksoket_target,public chsocket_adaptee
{
public:void ukplug() override{cout << "英国插座:";chplug();}
};

测试方法与主函数

void test()
{uksoket_target* uk1 = new uksoket_target();uksoket_target* uk2 = new uksocket_adapter();uk1->ukplug();uk2->ukplug();delete uk1;uk1 = nullptr;delete uk2;uk2 = nullptr;
}int main()
{test();return 0;
}
  1. 对象适配器

英国适配器(适配器类Adapter)

class uksocket_adapter : public uksoket_target
{
private:chsocket_adaptee* ch;
public:void ukplug() override{cout << "英国插座:";ch->chplug();}
};

测试方法与主函数

void test()
{uksoket_target* uk1 = new uksoket_target();uksoket_target* uk2 = new uksocket_adapter();uk1->ukplug();uk2->ukplug();delete uk1;uk1 = nullptr;delete uk2;uk2 = nullptr;
}int main()
{test();return 0;
}

五,优缺点

优点

  • 将目标类和适配器类解耦。通过引入一个适配器类来重用现有的适配者类,而无须修改原有的代码。

  • 增加了类的透明性和复用性,将具体的实现封装在适配器类中,对于客户端类来说是透明的,而且提高了适配器的复用性。

  • 灵活性和扩展性都非常好,符合开闭原则

缺点

  • 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。

六,适用场景

  • 当想使用一个已存在的类,而它的接口不符合需求时。

  • 你想创建一个可复用的类,该类可以与其他不相关的类或不可预见的类协同工作。


http://www.ppmy.cn/news/39347.html

相关文章

java -- Stringbuild、Date和Calendar类

Stringbuild类 由于String类的对象内容不可改变&#xff0c;每次拼接都会构建一个新的String对象&#xff0c;既耗时&#xff0c;又浪费内存空间 这时需要通过java提供的StringBuild类解决这个问题 StringBuilder又称为可变字符序列&#xff0c;它是一个类似于 String 的字符串…

贯穿设计模式第二话--开闭职责原则

&#x1f973;&#x1f973;&#x1f973; 茫茫人海千千万万&#xff0c;感谢这一刻你看到了我的文章&#xff0c;感谢观赏&#xff0c;大家好呀&#xff0c;我是最爱吃鱼罐头&#xff0c;大家可以叫鱼罐头呦~&#x1f973;&#x1f973;&#x1f973; 从今天开始&#xff0c;将…

Java基础之LinkedList

文章目录一、LinkedList介绍二、LinkedList特有方法 LinkedList应知应会2.1 调用addFirst() 方法在集合头部插入数据2.2 调用addLast() 方法在集合尾部追加数据2.3 调用getFirst() 方法获取集合第一个元素并返回元素值2.4 调用getLast() 方法获取集合最后一个元素并返回元素值2…

4.JAVA基础面试题:重要知识

四.JAVA基础面试题&#xff1a;重要知识 1.为什么JAVA只有值传递 2.JAVA获取运行时类的四种方式 3.动态代理和静态代理的对比 4.unsafe是什么 5.泛型擦除机制出现的问题&#xff1f; 四.JAVA基础面试题&#xff1a;重要知识 1.为什么JAVA只有值传递 实参&#xff1a;传递…

Flutter常用插件和对.yaml讲解

目录 一、对Flutter项目中的pubspec.yaml 进行讲解&#xff1a; 二、Flutter 常用插件 1、时间选择器 2、toast 3、RxDart 类似RxJava 和RxSwift 4、本地存储、保存--和Android sp 一样 5、数据库 6、获取包信息 7、下拉刷新&#xff0c;加载更多 8、google推荐--状态…

瑞吉外卖Day8Linux环境部署

MySQL数据库管理系统安装部署【简单】 简介 MySQL数据库管理系统&#xff08;后续简称MySQL&#xff09;&#xff0c;是一款知名的数据库系统&#xff0c;其特点是&#xff1a;轻量、简单、功能丰富。 MySQL数据库可谓是软件行业的明星产品&#xff0c;无论是后端开发、大数…

python 读取视频有多少帧并将视频转为GIF动态图

目录 1 python读取视频帧 2 python 将MP4格式视频前500帧转为动态图 3 python 将MP4格式视频第2688到2890帧转为动态图&#xff0c;并将gif图片的七分之一列和后七分之一列裁掉 4 python 将MP4格式视频第2688到2890帧转为动态图&#xff0c;并将gif图片的七分之一行和后七分…

R-CNN(Region with CNN feature)

目录 1. 介绍 2. R-CNN 2.1 SS(Selective Search) 算法 生成候选框 2.2 CNN 提取特征 2.3 SVM 分类 非极大值抑制 2.4 回归器微调候选框 3. R-CNN 的缺点 1. 介绍 目标识别的发展历史如图 2. R-CNN RCNN 是两阶段目标检测的鼻祖&#xff0c;类似于深度学习开山之作Al…