设计模式 - 结构型模式考点篇:适配器模式(类适配器、对象适配器、接口适配器)

目录

一、适配器模式

一句话概括结构式模式

1.1、适配器模式概述

1.2、案例

1.2.1、类适配器模式实现案例

1.2.2、对象适配器

1.2.3、接口适配器

1.3、优缺点(对象适配器模式)

1.4、应用场景


一、适配器模式


一句话概括结构式模式

教你将类和对象结合再一起形成一个更强大的结构.

1.1、适配器模式概述

将一个类的接口转换成客户希望的另一个接口,使得原本不兼容的接口能一起工作.

比如,如果你使用的是苹果手机,那么就意味着充电器的充电口也是苹果标准的,而你现在只有一个 type-c 插孔的插座能充电,因此就需要一个转换器(一头type-c,另一头 苹果插头),就可以让原本不兼容的 苹果插头 一起工作.

适配器模式包含以下主机角色:

  1. 目标接口:当前客户所期待的接口,它可以是抽象类或者接口(上述的 苹果插头).
  2. 适配者类:是被访问的现存组件库中的接口(上述的 type-c).
  3. 适配器类:是一个转换器,通过继承或引用目标接口,实现适配者类的所有方法,就可以实现转换效果.

适配器模式分为 类适配器模式、对象适配器模式 ,其中类适配器耦合度最高(不符合合成/聚合复用原则),且要求程序员了解现有组件库的内部结构,因此应用较少.

还有一种模式叫 接口适配器模式,是对对象适配器的扩展.

1.2、案例

现有一台电脑,只能读取 SD 卡,而我现在只有一个 TF 卡,因此就需要使用适配器模式. 创建一个读卡器,将 TF 卡中的内容读取出来.

1.2.1、类适配器模式实现案例

类适配器只需要我们继承目标接口,实现适配者接口的所有方法即可.

/*** 目标接口: TF 卡*/
public interface TFCard {/*** 读取 TF 卡* @return*/String readTF();/*** 写入 TF 卡*/void writeTF(String msg);}
/*** 目标接口实现类*/
public class TFCardImpl implements TFCard{@Overridepublic String readTF() {String msg = "tf card readTF: hello!";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card writeTF: hello!");}}
/*** 适配者接口: SD 卡*/
public interface SDCard {/*** 读取 SD 卡* @return*/String readSD();/*** 写入 SD 卡*/void writeSD(String msg);}
/*** 适配者实现类: SD 卡实现类*/
public class SDCardImpl implements SDCard {@Overridepublic String readSD() {String msg = "sd card readTF: hello!";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card writeTF: " + msg);}}
/*** 适配器:SD 兼容 TF*/
public class SDAdapterTF extends TFCardImpl implements SDCard{@Overridepublic String readSD() {System.out.println("adapter read tf card");return readTF();}@Overridepublic void writeSD(String msg) {System.out.println("adapter write tf card");writeTF(msg);}}
/*** 电脑类*/
public class Computer {public String readSD(SDCard sdCard) {if(sdCard == null) {throw new NullPointerException("sd card null");}return sdCard.readSD();}}
    public static void main(String[] args) {//1.创建一个电脑类Computer computer = new Computer();//3.通过适配器从电脑中读取 TF 卡的数据SDAdapterTF adapter = new SDAdapterTF();String msg = computer.readSD(adapter);System.out.println(msg);}

1.2.2、对象适配器

对象适配器,相比于 类适配器,更符合 合成/聚合复用原则(持有新对象的引用,而不是通过继承来达到复用目的).  也就是说,它是通过持有目标接口的引用(tf 卡接口的引用),重写 适配者接口 的所有方法实现的 .  

/*** 目标接口: TF 卡*/
public interface TFCard {/*** 读取 TF 卡* @return*/String readTF();/*** 写入 TF 卡*/void writeTF(String msg);}
/*** 目标接口实现类*/
public class TFCardImpl implements TFCard {@Overridepublic String readTF() {String msg = "tf card readTF: hello!";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card writeTF: hello!");}}

/*** 适配者接口: SD 卡*/
public interface SDCard {/*** 读取 SD 卡* @return*/String readSD();/*** 写入 SD 卡*/void writeSD(String msg);}
/*** 适配者实现类: SD 卡实现类*/
public class SDCardImpl implements SDCard {@Overridepublic String readSD() {String msg = "sd card readTF: hello!";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card writeTF: " + msg);}}
/*** 适配器:SD 兼容 TF*/
public class SDAdapterTF implements SDCard {private TFCard tfCard;public SDAdapterTF(TFCard tfCard) {this.tfCard = tfCard;}@Overridepublic String readSD() {System.out.println("adapter read tf card");return tfCard.readTF();}@Overridepublic void writeSD(String msg) {System.out.println("adapter write tf card");tfCard.writeTF(msg);}}
/*** 电脑类*/
public class Computer {public String readSD(SDCard sdCard) {if(sdCard == null) {throw new NullPointerException("sd card null");}return sdCard.readSD();}}
public class Client {public static void main(String[] args) {//1.创建一个电脑类Computer computer = new Computer();//3.通过适配器从电脑中读取 TF 卡的数据SDAdapterTF adapter = new SDAdapterTF(new TFCardImpl());computer.readSD(adapter);}}

1.2.3、接口适配器

当我们不希望实现一个适配者接口(sd 卡接口)中的所有方法时,可以创建一个抽象类 Adapter,实现所有方法(不用实现方法内容).此时我们只需要继承该抽象类,在重写我们需要的方法即可.

实现前两个适配器中,就一直没有使用 writeSD 方法,因此这里就不实现此方法.

/*** 目标接口: TF 卡*/
public interface TFCard {/*** 读取 TF 卡* @return*/String readTF();/*** 写入 TF 卡*/void writeTF(String msg);}
/*** 目标接口实现类*/
public class TFCardImpl implements TFCard {@Overridepublic String readTF() {String msg = "tf card readTF: hello!";return msg;}@Overridepublic void writeTF(String msg) {System.out.println("tf card writeTF: hello!");}}
/*** 适配者接口: SD 卡*/
public interface SDCard {/*** 读取 SD 卡* @return*/String readSD();/*** 写入 SD 卡*/void writeSD(String msg);}
/*** 适配者实现类: SD 卡实现类*/
public class SDCardImpl implements SDCard {@Overridepublic String readSD() {String msg = "sd card readTF: hello!";return msg;}@Overridepublic void writeSD(String msg) {System.out.println("sd card writeTF: " + msg);}}
public abstract class Adapter implements SDCard {@Overridepublic void writeSD(String msg) {}@Overridepublic String readSD() {return null;}}
public class SDAdapterTF extends Adapter implements SDCard{private TFCard tfCard;public SDAdapterTF(TFCard tfCard) {this.tfCard = tfCard;}@Overridepublic String readSD() {System.out.println("adapter read tf card");return tfCard.readTF();}
}
/*** 电脑类*/
public class Computer {public String readSD(SDCard sdCard) {if(sdCard == null) {throw new NullPointerException("sd card null");}return sdCard.readSD();}}
public class Client {public static void main(String[] args) {//1.创建一个电脑类Computer computer = new Computer();//2.通过适配器从电脑中读取 TF 卡的数据SDAdapterTF sdAdapterTF = new SDAdapterTF(new TFCardImpl());String msg = computer.readSD(sdAdapterTF);System.out.println(msg);}}

1.3、优缺点(对象适配器模式)

优点

1. 适配现有类,且不修改类:在不改变现有类的基础上,实现现有类和目标类的接口的匹配.

2. 符合 合成/聚合 复用原则:持有引用,而不继承.

3. 符合开闭原则:如果引入新的目标接口,只需要在适配器类中进行扩展,不需要修改原代码.

缺点:

增加复杂性:编写适配器类时,要考虑全面,包括适配者和目标类.

1.4、应用场景

1. 以前开发的系统中存在满足当前业务所需要的类,但是接口和当前业务所需接口不一致.

2. 第三方提供的组件,但是组件接口定义和自己要求的接口定义不同.

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

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

相关文章

阿里云上了新闻联播

我是卢松松,点点上面的头像,欢迎关注我哦! 阿里新任的CEO吴泳铭上央视新闻联播了! 在昨天的新闻联播里,出席科技座谈会,有一个特别镜头,出现了阿里新任CEO吴泳铭的镜头。 这个信号意义明显,我…

kali linux安装redis

官网:Install Redis from Source | Redis wget https://download.redis.io/redis-stable.tar.gztar -xzvf redis-stable.tar.gz cd redis-stable make显示如下即可进入下一步 sudo make installredis-server 可以看到已经可以使用了。 但是由于第一次使用导致了re…

Rust专属开发工具——RustRover发布

JetBrains最近推出的Rust集成开发工具——RustRover已经发布,官方网站:RustRover: Rust IDE by JetBrains JetBrains出品过很受欢迎的开发工具IntelliJ IDEA、PyCharm等。 RustRover优势 Rust集成环境,根据向导可自动下载安装rust开发环境提…

Centos7中安装Jenkins教程

1.必须先配置jdk环境,安装jdk参考 Linux配置jdk 2.先卸载Jenkins # rpm卸载 rpm -e jenkins # 检查是否卸载成功 rpm -ql jenkins # 彻底删除残留文件 find / -iname jenkins | xargs -n 1000 rm -rf 3.安装Jenkins 在 /usr/ 目录下创建 jenkins文件夹 mkdir -p je…

Maven 构建Java项目

Maven 使用原型 archetype 插件创建项目。要创建一个简单的 Java 应用,我们将使用 maven-archetype-quickstart 插件。 在下面的例子中,我们将在 C:\MVN 文件夹下创建一个基于 maven 的 java 应用项目。 命令格式如下: mvn archetype:gene…

微信小程序--》从模块小程序项目案例23.10.09

配置导航栏 导航栏是小程序的门户,用户进来第一眼看到的便是导航栏,其起着对当前小程序主题的概括。而我们 新建的小程序 时,第一步变开始配置导航栏。如下: 配置tabBar 因为配置tabBar需要借助字体图标,我这里平常喜…

【数据库——MySQL】(16)游标和触发器习题及讲解

目录 1. 题目1.1 游标1.2 触发器 2. 解答2.1 游标2.2 触发器 1. 题目 1.1 游标 创建存储过程,利用游标依次显示某部门的所有员工的实际收入。(分别用使用 计数器 来循环和使用 标志变量 来控制循环两种方法实现) 创建存储过程,将某部门的员工工资按工作…

前端js调试如何复制console.log打印的对象或数组

在使用console.log()打印我们的内容时,时常需要将打印的内容复制粘贴使用,然而控制台打印出来的对象是经过格式化处理且直接选择粘贴会有格式问题,此时我们可以通过控制台的 copy() 方法来进行打印结果的复制,如图所示&#xff1a…

使用python查找指定文件夹下所有xml文件中带有指定字符的xml文件

文件夹目录如下(需要递归删除文件夹下的.DS_Store文件): labels文件夹下面是xml文件: import os import os.pathpath "name/labels" files os.listdir(path) # 得到文件夹下所有文件名称 s []for xmlFile in files:…

华为云云耀云服务器L实例评测|企业项目最佳实践之云服务器介绍(一)

华为云云耀云服务器L实例评测|企业项目最佳实践系列: 华为云云耀云服务器L实例评测|企业项目最佳实践之云服务器介绍(一) 华为云云耀云服务器L实例评测|企业项目最佳实践之华为云介绍(二) 华为云云耀云服务器L实例评测&#xff5…

【轻松玩转MacOS】指引篇:这9篇指南助你轻松上手

引言 亲爱的读者,欢迎来到《轻松玩转MacOS》!这里是专为MacOS新手打造的使用教学专栏,无论您是从Windows转投Mac的初学者,还是对MacOS操作略知一二但希望更进一步的朋友,都能在这里找到您需要的答案。 正文 1、基本…

QT作业二

1、思维导图 https://www.zhixi.com/view/9e899ee0 2、作业 #include <iostream>using namespace std;class Rect {int width;int height; public:void init(int w,int h);//初始化函数void set_w(int w);//更改宽度void set_h(int h);//更改高度void show();//输出矩形…

你真的懂Java的继承吗?你知道什么时候用继承吗?设计继承是为了什么?

目录 1. 封装的意义是什么&#xff1f; 2. 为什么需要继承&#xff1f; 3. 继承是什么&#xff1f;如何使用&#xff1f; 4. 继承的好处是什么&#xff1f; 5. 设计继承需要注意什么&#xff1f; 6. 继承的特点 7. 子类到底继承了父类的哪些内容 7.1 继承内容 7.2 虚方…

【WSN】模拟无线传感器网络研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

html 笔记:CSS

1 什么是CSS CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素样式通常存储在样式表中 1.1 css的语法格式 1.1.1 选择器种类 HTML选择器&#xff1a; 重新定义HTML的某种标签的显示格式id选择器 对于HTML文档中的某个标签&#xff0c;定义它的显示格式…

JavaScript进阶(二十三):立即执行函数(匿名函数)( ( ) { } ( ) )含义解析

文章目录 一、前言二、立即执行函数2.1 立即执行函数使用的场景 三、拓展阅读 一、前言 前端项目改造过程中&#xff0c;引入的工具类实现如下&#xff1a; var tensquared(function(x) {return x*x; }(10)); 拆解以上语句如下&#xff1a; var tensquared xx; 这是赋值语句…

HTML5+CSS3+移动web 前端开发入门笔记(二)HTML标签详解

HTML标签&#xff1a;排版标签 排版标签用于对网页内容进行布局和样式的调整。下面是对常见排版标签的详细介绍&#xff1a; <h1>: 定义一级标题&#xff0c;通常用于标题栏或页面主要内容的标题。<p>: 定义段落&#xff0c;用于将文字分段展示&#xff0c;段落之…

Jmeter 链接MySQL测试

1.环境部署 1.1官网下载MySQL Connector https://dev.mysql.com/downloads/connector/j/ 1.2 解压后&#xff0c;将jar放到jmeter/lib目录下 1.3 在测试计划中添加引用 2.脚本设置 2.1设置JDBC Connection Configuration 先添加一个setUp线程中&#xff0c;在setUp中添加“…

2023年台州市第三届网络安全技能大赛(MISC)—Black Mamba

前言&#xff1a;当时比赛没有做出来现在来复现一下 就当记录一下&#xff08;这个思路没想到&#xff09; Black Mamba&#xff1a; 一张图片 常规得分离&#xff0c;属性&#xff0c;LSB&#xff0c;盲水印等都尝试过 无果&#xff01; 考点&#xff1a;异或解密&#xff0…

计算机算法分析与设计(8)---图像压缩动态规划算法(含C++代码)

文章目录 一、知识概述1.1 问题描述1.2 算法思想1.3 算法设计1.4 例题分析 二、代码 一、知识概述 1.1 问题描述 1. 一幅图像的由很多个像素点构成&#xff0c;像素点越多分辨率越高&#xff0c;像素的灰度值范围为0~255&#xff0c;也就是需要8bit来存储一个像素的灰度值信息…