• 彻底理解适配器模式


    适配器模式

    1. 概述

    • 适配器模式(Adapter Design Pattern)。这个模式就是用来做适配的,将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。(例如,现在有些手机只有一个Type-C接口,不能直接插入圆孔的有线耳机,这个时候就需要一个转接头将手机和耳机相连接,而适配器就相当于转接头)
    • 适配器模式的分类:
      • 类适配器:类适配器使用继承关系来实现,所以耦合度相对高一点。且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些
      • 对象适配器:对象适配器使用组合关系来实现。
      • 接口适配器:接口适配器适用于不需要实现接口中所有方法的情况

    2. 结构

    • 适配器模式包含以下主要角色:
      • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
      • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
      • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

    3. 类适配器模式

    案例:手机,手机的Type-C接口,圆孔耳机,转接头

    • 适配者类 adaptee:手机的Type-C接口

      public class TypeC {
          public TypeC(){
              System.out.println("转接头已通过Type-C连接手机");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 目标接口 target:圆孔耳机

      public interface Earphone {
          void connectEarphone();
      }
      
      • 1
      • 2
      • 3
    • 适配器 adapter:转接头

      public class Adapter extends TypeC implements Earphone{
      
          @Override
          public void connectEarphone() {
              System.out.println("转接头已连接耳机");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 手机

      public class Phone {
          public void listenMusicWithoutEarphone(){
              System.out.println("外放音乐");
          }
      
          public void listenMusicWhitEarphone(Adapter adapter){
              System.out.println("带上耳机听音乐");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 测试方法

      public class Test {
          public static void main(String[] args) {
      
              Phone phone = new Phone();//创建一个手机
              phone.listenMusicWithoutEarphone();//外放音乐
              System.out.println("=================");
              Adapter adapter = new Adapter();//创建一个转接头(转接头已自动连接手机)
              adapter.connectEarphone();//转接头连接耳机
              phone.listenMusicWhitEarphone(adapter);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 输出结果

      .

      类适配器模式违背了合成复用原则。因为Java的单继承性,所以类适配器模式只适用于客户类有一个接口规范的情况下,反之不可用。

    4. 对象适配器模式

    • 与上述案例中,只有适配器类有区别

      public class Adapter implements Earphone {
      
          private TypeC typeC;
      
          public Adapter(TypeC typeC){
              this.typeC = typeC;
          }
      
          @Override
          public void connectEarphone() { System.out.println("转接头已连接耳机"); }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 测试方法

      public class Test {
          public static void main(String[] args) {
              Phone phone = new Phone();
              phone.listenMusicWithoutEarphone();
              System.out.println("==================");
      
              Adapter adapter = new Adapter(new TypeC());
              adapter.connectEarphone();
              phone.listenMusicWhitEarphone(adapter);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 输出结果

      .

    5. 接口适配器模式

    • 当不需要全部实现接口提供的方法时,这时我们可以使用一个抽象类作为中间件,即适配器,用这个抽象类实现接口,而在抽象类中所有的方法都进行置空,那么我们再创建抽象类的继承类,而且重写我们需要使用的那几个方法即可。(如多头充电器)

    • target接口

      public interface Cable {
          //安卓充电线
          void android();
      
          //苹果充电线
          void apple();
      
          //Type-C充电线
          void typeC();
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • adapter抽象适配器

      public abstract class Adapter implements Cable {
      
          @Override
          public void android() {
      
          }
      
          @Override
          public void apple() {
      
          }
      
          @Override
          public void typeC() {
      
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
    • AndroidAdapter继承抽象适配器

      public class AndroidAdapter extends Adapter {
          private Current220V current220V;
      
          public AndroidAdapter(Current220V current220V){
              this.current220V = current220V;
          }
      
          @Override
          public void android() {
              System.out.println("安卓充电线线");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 测试方法

      public class Test {
          public static void main(String[] args) {
              Current220V current220V = new Current220V();
      
              AndroidAdapter adapter = new AndroidAdapter(current220V);
              adapter.android();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    6. 优点与缺点

    • 优点:
      • 能提高类的透明性和复用,现有的类复用但不需要改变。
      • 目标类和适配器类解耦,提高程序的扩展性。
      • 在很多业务场景中符合开闭原则。
    • 缺点:
      • 适配器编写过程需要全面考虑,可能会增加系统的复杂性。
      • 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。

    7. 使用场景

    1. Reader(字符流)、InputStream(字节流)的适配使用的是InputStreamReader。
    2. Spring框架

    8. 适配器模式与装饰模式的比较

    装饰器模式适配器模式
    形式有层级关系,是一种非常特别的适配器模式没有层级关系
    定义装饰器和被装饰器实现同一个接口,为了扩展之后保留OOP关系适配器和被适配者没有必然的联系,通常是采用继承或代理的形式进行包装
    功能注重覆盖注重兼容、转换
    设计前置考虑后置考虑
  • 相关阅读:
    别再用 Redis List 实现消息队列了,Stream 专为队列而生
    设计模式在交易系统的应用
    超详细的OpenCV入门教程,12小时带你吃透OpenCV。
    从 async 和 await 函数返回值说原理
    深度学习论文: MobileNetV4 - Universal Models for the Mobile Ecosystem及其PyTorch实现
    WAF防范原理
    1096 大美数
    coding上的免费的编译、打包、推镜像工具(cicd)太强了,必须分享一下
    Vue后台管理系统项目(32)SpuForm销售属性的数据展示
    Java反射调用jar包实现多态
  • 原文地址:https://blog.csdn.net/qq_52248567/article/details/126224217