【结构型模式】适配器模式

一、适配器模式概述

        适配器模式的定义-意图将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。(对象结构模式->对象适配器/类结构模式->类适配器)

        适配器模式包含三个角色:目标(Target)角色、适配者(Adaptee)角色和适配器(Adapter)角色。根据Adapter角色的实现不同,可分为类适配器和对象适配器

  • 类适配器模式(继承也是泛化实现):适配器角色对于被适配角色的适配是通过继承完成的还是通过组合来完成的。通过继承类适配者类(Adaptee Class)实现的,另外类适配器实现客户类所需要的接口。当客户对象调用适配器类方法的时候,适配器内部调用它所继承的适配者的方法。

  •  对象适配器模式(组合实现):适配器角色对于被适配角色的适配是通过组合来完成的。包含一个适配器者的引用(reference),与类适配器相同,对象适配器也实现了对客户类需要用接口。当客户对象调用对象适配器的方法的时候,对象适配器调它所包含的适配器者实例的适当方法。

  • 适配器模式的优缺点
    • 优点
      • 1.将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构;
      • 2.增加了类的透明性和复用性,提高了适配者的复用性,同一个适配者类可以在多个不同的体统中复用;
      • 3.灵活性和扩展性非常好;
      • 4.类适配器模式:置换一些适配者的发放很方便;
      • 5.对象适配器模式:可以把多个不同的适配者适配到同一个目标,还可以适配一个适配者的子类。
    • 缺点
      • 1.类适配器模式:
        • ①一次最多只能适配一个适配者类,不能同时适配多个适配者;
        • ②适配者类不能为最终类(不能为final);
        • ③目标抽象类只能为接口,不能为类。
      • 2.对象适配器模式:在适配器中置换适配者类的某些方法比较麻烦。
  • 适用环境
    • 1.系统需要使用一些现有的类,而这些类的接口不符合系统的需要,甚至没有这些类的源代码;
    • 2.创建一个可以重复使用的类,用于和一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。

二、缺省适配器

       缺省适配器模式(Defualt Adapter Pattern)的定义当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现该接口,并为借口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求,它适用于不想使用一个接口中的所有方法的情况,又成为单接口适配器模式

        结构

  • 适配者接口(ServiceInterface)
  • 缺省适配器类(AbstractServiceClass)
  • 具体业务类(ConcreteServiceClass)。

三、双向适配器

        双向适配器定义在对象适配器的使用过程,如果在适配器中同时包含对目标类和适配者类的引用,适配者可以通过对它调用目标类中的方法,目标类也可以通过它调用适配者类中的方法,那么该适配器就是一个双向适配器。

        结构

  • 目标(Target)角色
  • 适配者(Adaptee)角色
  • 适配器(Adapter)角色。

四、代码实现

        适配器模式的结构和实现:

  • 1.目标(Target)角色:这是客户所期待的接口。因为Java不支持多继承,所以Target必须是接口,不可以是类。
  • 2.适配者(Adaptee)角色:需要适配的类。
  • 3.适配器(Adapter)角色:把源接口转换成目标接口。
        4.1 对象适配器

        某公司欲开发一款儿童玩具汽车,为了更好地吸引小朋友的注意力,该玩具汽车在移动过程中伴随着灯光闪烁和声音提示。在该公司以往的产品中已经实现了控制灯光闪烁(例如警灯闪烁)和声音提示(例如警笛音效)的程序,为了重用先前的代码并且使得汽车控制软件具有更好的灵活性和扩展性,现使用适配器模式设计该玩具汽车控制软件。

        4.1.1 目标(Target)角色(CarController:汽车控制类,充当目标抽象类)
package Adapter.car;
//汽车控制类,充当目标抽象类
public abstract class CarController {public void move() {System.out.println("车开始移动!");}public abstract void phonate();//发出声音public abstract void twinkle();//灯光闪烁
}
        4.1.2 适配者(Adaptee)角色(PoliceSound:警笛类,充当适配者;PoliceLamp:警灯类,充当适配者)
package Adapter.car;
//警车声音类,充当适配器
public class PoliceSound {public void alarmSound() {System.out.println("发出警车声音!");}
}
package Adapter.car;
//警车灯类,充当适配者
public class PoliceLamp {public void alarmLamp() {System.out.println("呈现警车灯闪烁!");}
}
        4.2.3 适配器(Adapter)角色(PoliceCarAdapter:警车适配器,充当适配器)
package Adapter.car;
//适配器角色
public class PoliceCarAdapter extends CarController{//定义适配者PoliceSound对象private PoliceSound sound;//定义适配者PoliceLamp对象private PoliceLamp lamp;public PoliceCarAdapter() {sound=new PoliceSound();lamp=new PoliceLamp();}@Overridepublic void phonate() {// TODO 自动生成的方法存根sound.alarmSound();}@Overridepublic void twinkle() {// TODO 自动生成的方法存根lamp.alarmLamp();}}
        4.2.4 main方法实现对象适配器模式
package Adapter.car;public class Test {public static void main(String[] args) {// TODO 自动生成的方法存根CarController cc;//针对抽象目标编程//cc =new AmbulanceCarAdapter();//救护车适配器//cc.move();//cc.twinkle();//cc.phonate();System.out.println("----------------");cc=new PoliceCarAdapter();//警车适配器cc.move();cc.twinkle();cc.phonate();	}
}
        4.1.5 UML图

        4.2 缺省适配器

        本科生毕业条件:1.本科生必须读完读四年修满所有的学分后,参加论文答辩后即可毕业;2.学校采用的弹性学分制,只要修满所有的学分,可以提前安排答辩早毕业。

        要求:分别实现以下三种情况的学生类,并编写测试类运行。

  • 1)普通的就读四年的全日制大学生 GeneralStudent
  • 2)读了3年提前修满学分特殊的大学生SpecialStudent
  • 3)读到大二就退学的大学生DiscontinueStudyStudent
        4.2.1 目标(Target)角色(Study:学分接口,充当目标接口)

 

package Adapter.defualtAdapter.Student;
//目标Target角色
public interface Study {//四个学期和论文答辩public void StudyGrade1();public void StudyGrade2();public void StudyGrade3();public void StudyGrade4();public void TheisPresentation();
}
        4.2.2 适配者(Adaptee)角色(GeneralStudent、SpecialStudent、DiscountinueStudyStudent:充当适配者)

 

package Adapter.defualtAdapter.Student;
//Adaptee普通全日制大学生
public class GeneralStudent extends StudyAdapter{public GeneralStudent(String name) {super(name);}public void StudyGrade1(){System.out.println("读完大学一年级");}public void StudyGrade2(){System.out.println("读完大学二年级");}public void StudyGrade3(){System.out.println("读完大学三年级");}public void StudyGrade4(){System.out.println("读完大学四年级");}public void TheisPresentation() {super.TheisPresentation();System.out.println("修满了学分,参加论文答辩,成功毕业!");}
}
package Adapter.defualtAdapter.Student;
//Adaptee跳级的大学生
public class SpecialStudent extends StudyAdapter{public SpecialStudent(String name) {super(name);}public void StudyGrade1(){System.out.println("读完大学一年级");}public void StudyGrade2(){System.out.println("读完大学二年级");}public void TheisPresentation() {super.TheisPresentation();System.out.println("修满了学分,参加论文答辩,成功毕业!");}
}
package Adapter.defualtAdapter.Student;
//Adaptee辍学的大学生
public class DiscountinueStudyStudent extends StudyAdapter{public DiscountinueStudyStudent(String name) {super(name);}public void StudyGrade1(){System.out.println("读完大学一年级");}public void TheisPresentation() {super.TheisPresentation();System.out.println("中途辍学!");}
}
        4.2.3 适配器(Adapter)角色(StudyAdapter:学分适配器,充当适配器)
package Adapter.defualtAdapter.Student;
//适配器Adapter
public abstract class StudyAdapter implements Study{String name;public StudyAdapter(String name) {this.name=name;}public void StudyGrade1(){}public void StudyGrade2(){}public void StudyGrade3(){}public void StudyGrade4(){}public void TheisPresentation() {System.out.println("我是"+name);StudyGrade1();StudyGrade2();StudyGrade3();StudyGrade4();}
}
        4.2.4 main方法实现缺省适配器模式
package Adapter.defualtAdapter.Student;public class Test {public static void main(String[] args) {// TODO 自动生成的方法存根StudyAdapter s= new GeneralStudent("Emily");;//针对抽象目标接口编程s.TheisPresentation();System.out.println("-----------------------");StudyAdapter s1= new SpecialStudent("zz");;//针对抽象目标接口编程s1.TheisPresentation();System.out.println("-----------------------");StudyAdapter s2= new DiscountinueStudyStudent("xx");;//针对抽象目标接口编程s2.TheisPresentation();}}
        4.2.5 UML图

        4.3 双向适配器
  • 1.灰太狼临死前他将自己的抓羊秘技传给了已经成年的小灰灰,并留下一件狼皮和一件羊皮。小灰灰也承担起了抓羊的重任;
  • 2.小灰灰和羊相爱了,但是在梁山上,狼只能一直披着羊皮生活;
  • 3.小灰灰带媳妇回去看妈妈。

        他们改造成了一个新型的法宝——狼羊双向适配器。把羊皮和狼皮缝在一起,正面羊皮,翻过来后就是狼皮,这样一件衣服,既能扮狼又能扮羊。

        4.3.1 目标(Target)角色(ISheep、IWolf:充当目标接口)
package Adapter.doubleAdapter.wolfsheep;
//目标角色
public interface ISheep {public void sheepLooks();public void eatGrass();
}
package Adapter.doubleAdapter.wolfsheep;
//目标角色
public interface IWolf {public void wolfLooks();public void eatMeat();
}
        4.3.2 适配者(Adaptee)角色(Sheep、Wolf:充当适配者)
package Adapter.doubleAdapter.wolfsheep;
//适配者
public class Sheep implements ISheep {@Overridepublic void sheepLooks() {System.out.println("I am a sheep,too!");}@Overridepublic void eatGrass() {System.out.println("I eat grass!");}}
package Adapter.doubleAdapter.wolfsheep;
//适配者
public class Wolf implements IWolf {@Overridepublic void wolfLooks() {System.out.println("I am a wolf,too!");}@Overridepublic void eatMeat() {System.out.println("I eat meat!");}}
        4.3.3 适配器(Adapter)角色(TwoFaceAdapter:充当适配器)
package Adapter.doubleAdapter.wolfsheep;
//适配器
public class TwoFaceAdapter implements ISheep, IWolf {ISheep sheep =null;IWolf wolf =null;public TwoFaceAdapter(ISheep sheep) {this.sheep=sheep;}public TwoFaceAdapter(IWolf wolf) {this.wolf=wolf;}@Overridepublic void wolfLooks() {System.out.println("I am a wolf,too!");}@Overridepublic void eatMeat() {// TODO 自动生成的方法存根		sheep.eatGrass();}@Overridepublic void sheepLooks() {// TODO 自动生成的方法存根System.out.println("I am a sheep,too!");}@Overridepublic void eatGrass() {// TODO 自动生成的方法存根wolf.eatMeat();}}
        4.3.4 main方法实现双向适配器模式
package Adapter.doubleAdapter.wolfsheep;public class Test {public static void main(String[] args) {// TODO 自动生成的方法存根//把羊设配成狼ISheep fakersheep = new TwoFaceAdapter(new Wolf());fakersheep.sheepLooks();fakersheep.eatGrass();//把狼设配成羊IWolf fakerwolf = new TwoFaceAdapter(new Sheep());fakerwolf.wolfLooks();fakerwolf.eatMeat();}}
        4.3.5 UML图

五、代码结构图

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

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

相关文章

【运维】nginx配置解析

如果访问Nginx时出现502 Bad Gateway错误,则可能是Nginx主机上的SELinux限制了其使用http访问权限引起的,输入命令setsebool -P httpd_can_network_connect 1 开启权限即可。 nginx 基础配置 nginx 是一个功能非常强大的 web服务器加反向代理服务器&…

打破常规,重新定义PMP备考之路

今天我想和大家聊聊一个我们都不陌生的话题——PMP备考。你是不是也在备考的苦海中挣扎,或是听说过各种“速成”的神话?🤔 最近读到一篇文章(来着圣略PMP培训讲师老杨),让我对PMP备考有了新的认识。原来&a…

常见的地图绘制方法,这个包全包了~~

在上一篇介绍完Bokeh精美可视化作品之后,有小伙伴咨询我能不能稍系统的介绍下如何在地图上添加如柱形图等其他元素的付方法? 这就让我想到一个优秀的地图绘制可视化包-R-cartography,虽然之前也有简单介绍过,本期就具体分享下该包…

Python QP 求解器

系列文章目录 前言 该 Python 库提供一站式 solve_qp 函数,用于求解凸二次规划: 向量不等式逐个坐标应用。函数返回后端 QP 求解器找到的初等解 ,如果求解失败/问题不可行,则返回 None。所有求解器都要求问题是凸的,这…

CentOS 系统上使用 yum 安装 Nginx 及其模块

要在 CentOS 系统上使用 yum 安装 Nginx 及其 NJS (Nginx JavaScript Module),首先需要确保你的系统已经包含了 Nginx 的官方仓库,因为 Nginx 的某些模块可能不在默认的软件仓库中。 以下是安装 Nginx 和 Nginx Module NJS 的基本步骤: 添加…

探讨选择成为一名程序员的原因,是出于兴趣还是职业发展。

选择成为一名程序员的原因可以是出于兴趣和职业发展两方面的考虑。以下是两个方面的探讨: 兴趣:许多人选择成为程序员是因为对计算机科学和编程的兴趣。他们喜欢解决问题、构建应用程序和创造新的数字体验。对于这些人来说,编程是一种有趣、令…

隐式/动态游标的创建与使用

目录 将 emp 数据表中部门 10 的员工工资增加 100 元,然后使用隐式游标的 %ROWCOUNT 属性输出涉及的员工数量 动态游标的定义 声明游标变量 打开游标变量 检索游标变量 关闭游标变量 定义动态游标,输出 emp 中部门 10 的所有员工的工号和姓名 Orac…

光圈如何影响图像质量

光圈是摄影中一个重要的参数,它决定了镜头的光线通过量,直接影响图像的曝光和深度。以下是光圈如何影响图像质量的几个方面: 曝光控制:光圈的大小决定了相机接收到的光线的数量。较大的光圈(小光圈值)允许…

Ubuntu安装Java17

Ubuntu安装Java17 文章目录 Ubuntu安装Java171. 升级Ubuntu软件资源库2. 安装OpenJDK3. 检查是否安装成功4. 检查OpenJDK被安装在什么地方5. 设置全局环境变量 1. 升级Ubuntu软件资源库 $ sudo apt update && sudo apt upgrade -y2. 安装OpenJDK $ sudo apt-get inst…

攻防演练,作为红方,安装Amass进行子域名扫描

要在Ubuntu系统上安装并使用Amass进行子域名扫描,可以按照以下步骤操作。这个过程涵盖了从安装到实际使用的全程。 1. 安装Amass 有多种方法可以在Ubuntu上安装Amass。我将介绍两种常见的方法:使用Snap包管理器和从源代码安装。 使用Snap安装&#xf…

【Vue3】getters---Vue3中的计算属性工具

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…

多模态之ALBEF—先对齐后融合,利用动量蒸馏学习视觉语言模型表征,学习细节理解与论文详细阅读:Align before Fuse

Align before Fuse: Vision and Language Representation Learning with Momentum Distillation (ALBEF)在融合之前对齐:利用动量蒸馏进行视觉与语言表示学习 Paper: arxiv.org/pdf/2107.07651.pdf Github: https://github.com/salesforce/…

napi系列学习基础篇——如何通过DevEco Studio开发一个NAPI工程

简介 NAPI(Native API)是OpenHarmony系统中的一套原生模块扩展开发框架,它基于Node.js N-API规范开发,为开发者提供了JavaScript与C/C模块之间相互调用的交互能力。如下图所示: 这套机制对于鸿蒙系统开发的价值有两方…

权威认证!亚信安全9款产品入选CCIA首版《网络安全专用产品指南》

权威认证 近日,中国网络安全产业联盟(CCIA)正式发布《网络安全专用产品指南》(第一版)(以下简称《指南》),亚信安全凭借突出技术实力、创新优势以及业内深厚积累,旗下9款…

为什么VPS服务器是一个好的选择?

数字世界不断发展。无论是小型企业、中型企业还是大型企业,建立在线形象对于企业来说都变得非常重要。那么,在本文中,我们将主要讨论网站的托管服务器。有许多托管解决方案可供选择,而虚拟专用服务器(VPS)托管是业内最佳选择之一。…

学会 Python 后可以做什么副业?

近年来,Python凭借其简洁易入门的特点受到越来越多人群的青睐。 当然这不仅仅是针对程序员来说,对于一些学生、职场人士也是如此。 Python为什么会大受欢迎呢?因为Python还被大家称为“胶水语言,它适用于网站、桌面应用开发、[自…

大模型微调的几种常见方法

在文章深入理解大语言模型微调技术中,我们详细了解大语言模型微调的概念和训练过程,本篇给大家介绍大模型微调常见的7种训练方法。 1、Adapter Tuning 2019年谷歌的研究人员首次在论文《Parameter-Efficient Transfer Learning for NLP》提出针对 BERT 的…

Matlab求矩阵的逆,3种常用方法总结

几种求逆矩阵的方法总结,以Matlab语言为例 *0* 引言*1* 简单描述函数实现*2* 方法调用计算对比 0 引言 最近在使用函数库求解逆矩阵的时候发现同一个矩阵使用不同的语言、不同的求解方法会产生不同精度的结果,特别是阶数很高的方阵,一些库中的…

第14章 大数据与数据科学知识点梳理

第14章 大数据与数据科学知识点梳理(附带页码) ◼ 原则:组织应仔细管理与大数据源相关的元数据,以便对数据文件及其来源和价值进行准确的清单管理。P386 ◼ 大数据:数据量大(Volume)、数据更新…

未来计算机的发展趋势是什么?

未来计算机的发展趋势是多方面的,涵盖了硬件、软件、体系结构以及计算范式等多个层面。以下是一些预期的趋势: 1. 量子计算: 随着量子理论的不断成熟和技术的进步,量子计算机将可能解决传统计算机难以处理的问题,比如药物发现、材料科学、复杂系统模拟等领域。量子计算的…