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

简介: 这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。

适配器模式 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适配器模式的最大作用就是将原本不兼容的接口融合在一起工作。


相关文章
|
9天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
6天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2501 14
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
6天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1517 14
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
8天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
523 12
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19282 30
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18836 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17523 13
Apache Paimon V0.9最新进展
|
8天前
|
人工智能 自动驾驶 机器人
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
过去22个月,AI发展速度超过任何历史时期,但我们依然还处于AGI变革的早期。生成式AI最大的想象力,绝不是在手机屏幕上做一两个新的超级app,而是接管数字世界,改变物理世界。
452 48
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
|
22小时前
|
云安全 存储 运维
叮咚!您有一份六大必做安全操作清单,请查收
云安全态势管理(CSPM)开启免费试用
352 4
叮咚!您有一份六大必做安全操作清单,请查收
|
2天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。