设计模式--适配器模式 Adapter Pattern

news2024/11/17 17:55:24

设计模式--适配器模式 Adapter Pattern

  • 适配器模式 Adapter Pattern
    • 1.1 基本介绍
    • 1.2 工作原理
  • 类适配器模式
  • 对象适配器模式
  • 接口适配器模式
  • 小结

适配器模式 Adapter Pattern

1.1 基本介绍

(1)适配器模式将某个类的接口转换成为客户端期望的另一个接口表示,主要的目的是兼容性,让原本应接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper).

(2)适配器模式属于结构型模式

(3)主要分为三类:类适配器模式、对象适配器模式、接口适配器模式

1.2 工作原理

  1. 适配器模式:将一个类的接口转换成为另一种接口,让原本接口不兼容的类可以兼容。
  2. 从用户的角度看不到被适配者,是解耦的。
  3. 用户调用适配器转换出来的目标接口方法,适配器再调用被适配者的相关接口方法。
  4. 用户收到反馈结果,感觉只是和目标接口交互。

类适配器模式

例子:电脑的电源适配器将(家庭用电)电压220伏特转换为5伏特,然后给电脑供电。

被适配者类:

package com.robin.adapter.classAdapter;

// 被适配者类
public class Voltage220V {

    public int outPut220V(){
        int srcV = 220;
        System.out.println("[初始-家庭家用电压]电源电压:"+srcV+"伏特");
        return srcV;
    }
}

适配接口:

package com.robin.adapter.classAdapter;

// 适配接口
public interface ICpVoltage5V {

    public int outPut();
}

电脑类:

package com.robin.adapter.classAdapter;

public class Computer {

    public void charge(ICpVoltage5V iCpVoltage5V){
        int i = iCpVoltage5V.outPut();
        if (i==5){
            System.out.println("[电源适配器]电压为5伏特,可以开始充电使用了!");
        }else{
            System.out.println("[电源适配器]电压不正常,请检查或者更换电源适配器");
        }
    }
}

适配器类:

package com.robin.adapter.classAdapter;

// 适配器类
public class CpVoltageAdapter extends Voltage220V implements ICpVoltage5V{

    @Override
    public int outPut() {
        // 因为是继承关系,所以调用其父类的 电源电压输出
        int src = outPut220V();
        // 对220V电压进行简单转换
        int dest = src/44;
        return dest;
    }
}

测试客户端类:

package com.robin.adapter.classAdapter;

public class Client {

    public static void main(String[] args) {
        Computer computer = new Computer();
        // 通过传入其适配器类的对象来进行充电
        computer.charge(new CpVoltageAdapter());
        // [电源适配器]电压为5伏特,可以开始充电使用了!
    }
}

类适配器模式的优点和缺点:

  1. 缺点:Java是单继承,但再类适配器模式中,适配器类需要继承被适配的类,失去了灵活性。并且被适配者类的方法都会在适配器类中暴露出来,增加了使用的成本。
  2. 优点:因为适配器类继承了被适配者类,所以适配器类可以根据需求,灵活的重写被适配者类。

对象适配器模式

对象适配器模式针对上面的类适配器模式进行了一些修改,通过合成复用来代替原本的继承关系

tip:对象适配器模式是适配器模式中常用的一种。

例子:还是上面的电脑电源的适配器问题,进行修改,将其改为对象适配器模式的。

我们只需要将适配器类中取消继承被适配的类,然后在适配器类中提供一个被适配类的成员变量及构造器即可。

在这里插入图片描述

被适配者类:

package com.robin.adapter.objectAdapter;

// 被适配者类
public class Voltage220V {

    public int outPut220V(){
        int srcV = 220;
        System.out.println("[初始-家庭家用电压]电源电压:"+srcV+"伏特");
        return srcV;
    }
}

适配接口:

package com.robin.adapter.objectAdapter;

// 适配接口
public interface ICpVoltage5V {

    public int outPut();
}

电脑类:

package com.robin.adapter.objectAdapter;


public class Computer {

    public void charge(ICpVoltage5V iCpVoltage5V){
        int i = iCpVoltage5V.outPut();
        if (i==5){
            System.out.println("[电源适配器]电压为5伏特,可以开始充电使用了!");
        }else{
            System.out.println("[电源适配器]电压不正常,请检查更换电源适配器");
        }
    }
}

适配器类:

package com.robin.adapter.objectAdapter;

// 适配器类
public class CpVoltageAdapter implements ICpVoltage5V {

    // 合成复用 将被适配类聚合到适配器类中
    private Voltage220V  voltage220V = null;

    // 提供被适配类的构造器
    public CpVoltageAdapter(Voltage220V voltage220V) {
        this.voltage220V = voltage220V;
    }

    // 重写适配接口中的方法
    @Override
    public int outPut() {
        if (null != voltage220V){
            int srcV = voltage220V.outPut220V();
            int dstV = srcV/44;
            System.out.println("电源电压适配完成,电源电压="+dstV);
            return dstV;
        }
        return -1;
    }
}

客户端测试类:

package com.robin.adapter.objectAdapter;

public class Client {

    public static void main(String[] args) {
        System.out.println("对象适配器模式");
        Computer computer = new Computer();
        computer.charge(new CpVoltageAdapter(new Voltage220V()));
    }
}

对象适配器模式与类适配器模式基本一致,只是通过合成复用代替继承,解决了类适配器产生的继承局限问题,使用成本更低更灵活。

接口适配器模式

接口适配器模式的思想:当不需要全部实现接口提供的方法时,可以先设计一个抽象类实现接口,并为该接口中的每个方法提供一个默认实现(空方法体),那么该抽象类的子类可以有选择的覆盖父类的某些方法来实现需求。

接口适配器模式适用于不想使用一个适配接口中所有方法的情况,按照自己的需求来挑选合适的方法自行实现。

比如,你要去旅游了,每个国家插座插孔和电压都不一样,你带了一个万能转换器(比如:wp-933)

在这里插入图片描述

然后各国插座如下:

在这里插入图片描述

暂且假定该万能转换插孔只提供一个空的插孔,需要你去自定义实现(我例子举得不是很好…有点牵强)

万能插孔适配接口:

package com.robin.adapter.interfaceadpter;

// 万能插孔适配接口
public interface AllJacks {

    // 德国标准
    public void germanJack();
    // 欧洲标准
    public void europeanJack();
    // 中国,澳大利亚标准
    public void chinaAndOzJack();
    // 美国标准
    public void usaJack();
    //......
}

万能插孔抽象类实现接口中的所有方法,提供空方法体:

package com.robin.adapter.interfaceadpter;

// 抽象类实现万能适配接口,实现全部接口方法,提供空方法体
public abstract class AbsAllJacksAdapter implements AllJacks {

    // 德国
    @Override
    public void germanJack() {

    }

    // 欧洲
    @Override
    public void europeanJack() {

    }

    // 中国和澳大利亚
    @Override
    public void chinaAndOzJack() {

    }

    // 美国
    @Override
    public void usaJack() {

    }
}

客户端测试:

package com.robin.adapter.interfaceadpter;

public class Client {

    public static void main(String[] args) {
        // 中国电脑插孔为三孔,方形
        String srcJack = "[三孔]三方形孔";
        // 假设我现在旅行去美国
        AbsAllJacksAdapter absAllJacksAdapter = new AbsAllJacksAdapter(){
            @Override
            public void usaJack() {
                System.out.println("=============使用万能转化器转换=============");
                // 美国电压为 100-130V,插孔为三孔,两方一圆
                String destJack = "[三孔]两方一圆孔";
                System.out.println("[插孔适配完毕]:"+srcJack+"==>"+destJack);
            }
        };
        absAllJacksAdapter.usaJack();
    }
}

在这里插入图片描述

小结

适配器模式的三种方式,也其实就是被适配类,如何被适配器类获取使用的(类=>继承,对象=>合成复用,接口)。Adapter适配器模式的最大作用就是将原本不兼容的接口融合在一起工作。


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

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

相关文章

普通人如何改变自己的命运?

【Morty】普通人改变命运的秘密!我的观点可能会颠覆你的认知_哔哩哔哩_bilibili 非常感谢UP,你的每个视频我都看了,给我启示最大的是《为什么你总是那么穷》,这些年一直走背运,加上20年创业失败了,已经身无…

LAMP架构介绍及配置

LAMP架构介绍及配置一、LAMP简介与概述1、LAMP平台概述2、LAMP各组件主要作用3、构建LAMP平台二、编译安装Apache htpd服务1、将所需软件包上传到/opt目录下2、解压以下文件3、移动两个文件并改名4、安装所需工具5、编译安装6、做软连接,使文件可执行7、优化配置文件…

面试题:Java锁机制

java对象包含了三个部分:对象头,实例数据和对齐填充。对象头又存放了:markWord和class point。classpoint :指向方法区,当前对象的类信息数据。markword:存储了很多和当前对象运行时的数据:例如…

【Spark分布式内存计算框架——Spark Core】7. RDD Checkpoint、外部数据源

第五章 RDD Checkpoint RDD 数据可以持久化,但是持久化/缓存可以把数据放在内存中,虽然是快速的,但是也是最不可靠的;也可以把数据放在磁盘上,也不是完全可靠的!例如磁盘会损坏等。 Checkpoint的产生就是…

六、mybatis与spring的整合

Spring整合Mybaits的步骤 引入依赖 在Spring整合Mybaits的时候需要引入一个中间依赖包mybatis-spring <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version> </dependency&g…

通过抓包分析gPRC协议

通过抓包分析gPRC协议 前言 gRPC 是一个高性能、开源和通用的 RPC 框架&#xff0c;面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本&#xff0c;分别是&#xff1a;grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C, Node.js, Python, Ruby, Objective-C, PHP 和 …

windows + vscode + rust

1 安装VSCODE略2 安装rust插件1、说明&#xff1a;第4步本人是一个一个点击状态。上图禁用按钮在没装之前是显示“安装”按钮&#xff0c;应该点击“安装”也可以。2、还需要安装C插件&#xff0c;搜索C即可&#xff0c;装微软的3 创建rust工程由于初次使用&#xff0c;不知道目…

实战项目-课程潜在会员用户预测(朴素贝叶斯&神经网络)

目录1、背景介绍2、朴素贝叶斯2.1 模型介绍2.2 模型实现3、人工神经网络1、背景介绍 目标&#xff1a;将根据用户产生的数据对课程潜在的会员用户&#xff08;可能产生购买会员的行为&#xff09;进行预测。 平台的一位注册用户是否购买会员的行为应该是建立在一定背景条件下…

TCP、UDP网络编程面试题

TCP、UDP、Socket、HTTP网络编程面试题 什么是网络编程 网络编程的本质是多台计算机之间的数据交换。数据传递本身没有多大的难度&#xff0c;不就是把一个设备中的数据发送给其他设备&#xff0c;然后接受另外一个设备反馈的数据。现在的网络编程基本上都是基于请求/响应方式…

linux 进程

文章目录1、进程的状态2、进程的组织3、进程的控制3.1、进程的创建fork 函数fork 拷贝和共享fork 原理fork 的写时复制exec 函数族exec 原理3.2、进程的终止exit 函数* 僵死进程* 孤儿进程3.3、进程的阻塞和唤醒3.4、进程的切换4、进程间通信5、进程调度算法进程是可执行程序的…

特斯拉无人驾驶解读

来源于Tesla AI Day Tesla无人驾驶算法的核心任务就是如何理解我们所看到的一切呢?也就是说,不使用高端的设备,比如激光雷达,仅仅使用摄像头就能够将任务做得很好。Tesla使用环绕型的8个摄像头获得输入。 第一步是特征提取模块Backbone,无论什么任务都离不开特征…

chatgpt怎么安装?国内怎么玩chatgpt?

关于chatgpt的传言最近真的是闹得沸沸扬扬&#xff0c;主要是这个chatgpt人工智能的冲击力实在是太大了&#xff0c;它学习了大量的语言知识&#xff0c;具有很强的语言能力&#xff0c;无论是写作&#xff0c;还是诗歌&#xff0c;甚至是代码都是不在话下&#xff0c;美国大学…

【数据库】 如何对数据库进行操作

目录 一&#xff0c;SQL语句基础 1&#xff0c; SQL简介 &#xff08;1&#xff09; SQL语句分类 &#xff08;2&#xff09;SQL语句的书写规范 二&#xff0c;数据库操作 1、查看 &#xff08;1&#xff09;查看所有数据库 &#xff08;2&#xff09;查看有没有指定的数…

ubuntu20下Qt5.14.2+OpenCV(含Contrib)-4.5.0环境搭建

Qt若要能处理图片和视频&#xff0c;就必须安装OpenCV&#xff0c;而OpenCV中很多的高级功能如人脸识别等都包含在Contrib扩展模块中&#xff0c;需要将Contrib与OpenCV一起联合编译&#xff0c;目前所用这两个版本都是4.5.0版。 一、下载OpenCV OpenCV的官方下载地址为http:…

SSM整合SpringSecurity简单使用

一、SpringSecurity 1.1 什么是SpringSecurity Spring Security 的前身是 Acegi Security &#xff0c;是 Spring 项目组中用来提供安全认证服务的框架。(官网地址) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发…

用网络调试助手测试PLC-Reocrder收听模式的过程

目录 一、测试环境 二、步骤及要点说明 1、PLC-Recorder的通道配置 2、PLC-Recorder启动采集 3、配置网络调试助手 4、启动调试助手的连接&#xff0c;并点击“启动批量发送” 5、停止发送&#xff0c;查看发送和接收的情况 三、小结 一、测试环境 Windows10操作系统&a…

Docker进阶 - 11. Docker Compose 编排服务

注&#xff1a;本文只对一些重要步骤和yml文件进行一些讲解&#xff0c;其他的具体程序没有记录。 目录 1. 原始的微服务工程编排(不使用Compose) 2. 使用Compose编排微服务 2.1 编写 docker-compose.yml 文件 2.2 修改并构建微服务工程镜像 2.3 启动 docker-compose 服务…

数据结构(二):单向链表、双向链表

数据结构&#xff08;二&#xff09;一、什么是链表1.数组的缺点2.链表的优点3.链表的缺点4.链表和数组的区别二、封装单向链表1. append方法&#xff1a;向尾部插入节点2. toString方法&#xff1a;链表元素转字符串3. insert方法&#xff1a;在任意位置插入数据4.get获取某个…

RNN神经网络初探

目录1. 神经网络与未来智能2. 回顾数据维度和神经网络1. 神经网络与未来智能 2. 回顾数据维度和神经网络 循环神经网络&#xff0c;主要用来处理时序的数据&#xff0c;它对每个词的顺序是有要求的。 循环神经网络如何保存记忆功能&#xff1f; 当前样本只有 3 个特征&#x…

git基本概念图示【学习】

基本概念工作区&#xff08;Working Directory&#xff09;就是你在电脑里能看到的目录&#xff0c;比如名字为 gafish.github.com 的文件夹就是一个工作区本地版本库&#xff08;Local Repository&#xff09;工作区有一个隐藏目录 .git&#xff0c;这个不算工作区&#xff0c…