设计模式之适配器模式(通俗易懂--代码辅助理解【Java版】)

文章目录

设计模式概述

创建型模式:工厂方法、抽象方法、建造者、原型、单例。

结构型模式有:适配器、桥接、组合、装饰器、外观、享元、代理。

行为型模式有:责任链、命令、解释器、迭代器、中介、备忘录、观察者、状态、策略、模板方法、访问者。

常用设计模式:

单例模式、工厂模式、代理模式、策略模式&模板模式、门面模式、责任链模式、装饰器模式、组合模式、builder模式。

1、适配器模式

  • 适配器模式(Adapter Pattern )充当两个不兼容接口之间的桥梁,属于结构型设计模式。它通过一个中间件(适配器)将一个类的接口转换成客户期望的另一个接口,使原本不能一起工作的类能够协同工作。

  • 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

2、适配器模式的使用场景

  • 假设有一部手机,它只能接受typec口输入或输出;还有一个投影仪,投影仪只能接受vga口作为输入或输出;现在,我们需要实现手机屏幕投影到投影仪上,可以通过创建一个适配器来实现:

    • 目标接口:现有的投影仪只能接受vga口。
    • 适配者类:手机的输出口为typec口。
    • 适配器类:创建一个新的类,实现目标接口,并在内部使用适配者类来将视频信号从typec口输入,转换输出到vga口,才能和投影仪对接。

3、优点

  • 促进了类之间的协同工作,即使它们没有直接的关联。
  • 提高了类的复用性。
  • 增加了类的透明度。
  • 提供了良好的灵活性。

4、缺点

  • 过度使用适配器可能导致系统结构混乱,难以理解和维护。
  • 在Java中,由于只能继承一个类,因此只能适配一个类,且目标类必须是抽象的

5、主要角色

  • 目标接口(Target):定义客户需要的接口。
  • 适配者类(Adaptee):定义一个已经存在的接口,这个接口需要适配。
  • 适配器类(Adapter):实现目标接口,并通过组合或继承的方式调用适配者类中的方法,从而实现目标接口。

6、代码示例

1)UML图

2)源代码

(1)定义一部手机,它有个typec口。

java 复制代码
/**
 * @author jstao
 * 定义一个手机Phone,它有一个Typec接口。
 * 
 */
public class Phone {
    public void typecPhone() {
        System.out.println("信息从Typec口的手机输出。");
    }
}

(2)定义一个vga接口。

java 复制代码
/**
 * @author jstao
 * 定义一个VGA接口。
 * 
 */
public interface Vga {
    void vgaInterface();
}

(3)实现一个适配器,适配器实现方式分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

1】类的适配器模式(通过继承特性来实现适配器功能)
java 复制代码
/**
 * 
 * 实现一个Type-c转VGA适配器,
 * 适配器实现方式有三种,这是第一种实现方式。
 * @author jstao
 *
 */
public class Typec2Vga1 extends Phone implements Vga{
    @Override
    public void vgaInterface() {
        // TODO Auto-generated method stub
        typecPhone();
        System.out.println("接收到Type-c口信息,信息转换成VGA接口中...");
        System.out.println("信息已转换成VGA接口,显示屏可以对接。");
    }
}
2】对象的适配器模式(通过组合方式来实现适配器功能)
java 复制代码
/**
 * 
 * 实现一个Type-c转VGA适配器,
 * 适配器实现方式有三种,这是第二种实现方式。
 * @author jstao
 *
 */
public class Typec2Vga2 implements Vga{

    private Phone phone;
    
    public Typec2Vga2(Phone phone) {
        // TODO Auto-generated constructor stub
        this.phone = phone;
    }
    
    @Override
    public void vgaInterface() {
        // TODO Auto-generated method stub
        if(phone != null) {
            phone.typecPhone();
            System.out.println("接收到Type-c口信息,信息转换成VGA接口中...");
            System.out.println("信息已转换成VGA接口,显示屏可以对接。");
        }
    }
}
3】接口的适配器模式(借助抽象类来实现适配器功能)

定义三个接口

java 复制代码
/**
 * 定义接口
 * @author jstao
 *
 */
public interface Target {
    
    void typec();
    void typec2vga();
    void typec2hdmi();
}

定义一个抽象类

java 复制代码
/**
 * 定义一个抽象类
 * @author jstao
 *
 */
public abstract class Adapter implements Target{

    public void typec() { }
    
    public void typec2vga() { }
    
    public void typec2hdmi() { }
}

实现一个vga适配器

java 复制代码
/**
 * 
 * 实现一个VGA适配器,同理还可以实现一个HDMI适配器
 * 适配器实现方式有三种,这是第三种实现方式。
 * @author jstao
 *
 */
public class VgaAdapter extends Adapter{
    
    public void typec() {
        System.out.println("信息从Typec口的手机输出。");
    }
    
    public void typec2vga() {
        System.out.println("接收到Type-c口信息,信息转换成VGA接口中...");
        System.out.println("信息已转换成VGA接口,显示屏可以对接。");
    }
}

(4)定义一个显示屏,用来测试上面实现的三个适配器。

java 复制代码
/**
 * 定义一个显示屏
 * 与适配器对接
 * @author jstao
 *
 */
public class Screen {
    public static void main(String[] args) {
        //第一种适配器用法
        System.out.println("-------------第一种适配器------------");
        Vga vga = new Typec2Vga1();
        vga.vgaInterface();//适配器将typec转换成vga
        System.out.println("显示屏对接适配器,手机成功投影到显示屏!");
        
        //第二种适配器用法
        System.out.println("-------------第二种适配器------------");
        Typec2Vga2 typec2Vga1 = new Typec2Vga2(new Phone());
        typec2Vga1.vgaInterface();//适配器将typec转换成vga
        System.out.println("显示屏对接适配器,手机成功投影到显示屏!");
        
        //第三种适配器用法
        System.out.println("-------------第三种适配器------------");
        VgaAdapter vgaAdapter = new VgaAdapter();
        vgaAdapter.typec();
        vgaAdapter.typec2vga();//适配器将typec转换成vga
        System.out.println("显示屏对接适配器,手机成功投影到显示屏!");
    }
}

7、总结

  • 适配器模式在源码中的应用:

    • (1)JDK源码的IO模块用到,例如 java.io.InputStreamReader(InputStream)、java.io.OutputStreamWriter(OutputStream)。
    • (2)mybatis源码日志模块用到对象适配器模式。
  • 适配器模式将一个接口转为另外一个接口。它有三种实现方式:

    • (1)当希望将一个类转换为满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

    • (2) 当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Typec2Vga2 类,持有原类的一个实例,在Typec2Vga2 类的方法中,调用实例的方法就行。

    • (3)当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法,我们写别的类的时候,继承抽象类即可。

相关推荐
今天你TLE了吗16 分钟前
JVM学习笔记:第八章——执行引擎
java·jvm·笔记·后端·学习
java1234_小锋22 分钟前
Java高频面试题:Redis里什么是缓存击穿、缓存穿透、缓存雪崩?
java·redis·缓存
me83222 分钟前
【Java】踩坑实录:Spring Boot + Nginx 本地部署404终极排查:从80端口被占用到配置生效全流程
java·spring boot·nginx
6+h25 分钟前
【Spring】AOP核心之原始对象与代理对象
java·python·spring
君爱学习26 分钟前
SpringCloud-微服务拆分
java
礼拜天没时间.31 分钟前
力扣热题100实战 | 第25期:K个一组翻转链表——从两两交换到K路翻转的进阶之路
java·算法·leetcode·链表·递归·链表反转·k个一组翻转链表
y = xⁿ1 小时前
【从零开始学习Redis|第四篇】从底层理解缓存问题:雪崩、击穿、穿透与一致性设计
java·redis·学习·缓存
江湖有缘1 小时前
本地化JSON 处理新方案:基于 Docker的JSON Hero部署全记录
java·docker·json
御坂10101号1 小时前
「2>&1」是什么意思?半个世纪的 Unix 谜题
java·数据库·bash·unix
鱼骨不是鱼翅1 小时前
个人简历面试复习-----设计模式篇(一)
设计模式