设计模式--适配器模式

简介

适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主要目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作

举个例子:在生活中家用电压一般是220V,手机的充电电压通常是5v,如果直接把家用电压接到电池接到电池两极直接充电的话,电池会烧掉。这个时候充电器就扮演一个适配器的角色,使得家用电源能够安全的给手机电池充电


组成

  1. 目标接口(target):当前系统业务所期望的接口,它可以是具体的类、抽象类、接口

  2. 适配者类(adaptor):它是被适配的对象,已有接口,但和目标接口不兼容

  3. 适配器(adapter):它是一个转换器,把适配者接口转为目标接口,让客户按目标接口的格式访问适配者


实现方式

类适配器模式

适配器类(adapter)通过 继承 适配者类(adaptor),并实现 目标接口(target),完成适配者类到目标接口的转换

  • 适配者类
    • public class Voltage220V {
      
          private static final int voltage = 220;
      
          public int outputVoltage220V(){
              return voltage;
          }
      }
  • 目标接口
    • public interface Voltage5V {
          int outputVoltage5V();
      }
  • 适配器类
    • public class VoltageAdapter extends Voltage220V implements Voltage5V{
      
          @Override
          public int outputVoltage5V() {
              //适配转换
              int voltage220V = outputVoltage220V();
      
              return voltage220V / 44;
          }
      }
  • 测试
    • public class Test {
          public static void main(String[] args) {
              VoltageAdapter voltageAdapter = new VoltageAdapter();
              System.out.println(voltageAdapter.outputVoltage5V());
          }
      }

缺点:

  • Java是单继承的,适配器类继承适配者类,所以目标接口必须要是接口类,有一定局限性
  • 因为适配器继承了适配者类,所以会导致适配器中可以直接访问适配者类的一些其他方法或变量,增加使用成本,但同样地它也可以重写这些方法

对象适配器模式

适配器通过持有适配者类的实例(如以成员变量的方式持有),然后实现目标接口从而完成适配者与目标接口的兼容

  • 适配者类
    • public class Voltage220V {
      
          private static final int voltage = 220;
      
          public int outputVoltage220V(){
              return voltage;
          }
      }
  • 目标接口
    • public interface Voltage5V {
      
          int outputVoltage5V();
      }
  • 适配器
    • public class VoltageAdapter implements Voltage5V{
      
          private Voltage220V voltage220V;
      
          public VoltageAdapter(Voltage220V voltage220V){
              this.voltage220V = voltage220V;
          }
      
          @Override
          public int outputVoltage5V() {
      
              int voltage5V = 0;
      
              if (voltage220V != null) {
                  //适配转换
                  int voltage = voltage220V.outputVoltage220V();
                  voltage5V = voltage / 44;
              }
      
              return voltage5V;
          }
      }
  • 测试
    • public class Test {
          public static void main(String[] args) {
              Voltage220V voltage220V = new Voltage220V();
              VoltageAdapter voltageAdapter = new VoltageAdapter(voltage220V);
              System.out.println(voltageAdapter.outputVoltage5V());
          }
      }

优势:

  1. 使用组合替代继承, 解决了类适配器必须继承适配者类的局限性问题,同时也不再要求目标接口类必须是接口。相对于类适配器一种更灵活的实现方式

缺省适配器模式

缺省适配器模式为一个接口提供缺省实现类,通常该类是一个抽象类,该抽象类作为中间层实现接口所有方法,默认为空实现,这样就可以从这个缺省实现进行扩展,而不必从原有的接口进行扩展。当原接口中定义方法过多,而其中大部分方法又不是需要的时候,可使用这种模式

  • 接口
    • public interface FunctionInterface {
          void start();
          void init();
          void end();
      }
  • 抽象类---对接口进行默认实现
    • public abstract class AbstractAdapter implements FunctionInterface{
      
          @Override
          public void start() {
      
          }
      
          @Override
          public void init() {
      
          }
      
          @Override
          public void end() {
      
          }
      }
  • 继承抽象类选择性重写方法以实现适配
    • public class AbstractAdapterImpl extends AbstractAdapter {
      
          @Override
          public void init() {
              //只需要去覆盖 需要使用 接口方法
              System.out.println("init");
          }
      }

优势:适用于当原接口中定义的方法太多,而其中大部分又不被需要时,使用这种模式选择性的实现一些方法


优势和缺点

优势:

  • 将接口或数据转换代码从程序主要业务逻辑中分离,符合单一职责原则
  • 只要客户端代码通过客户端接口与适配器进行交互 就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器,符合开闭原则

缺点:

  • 代码整体复杂度增加 因为你需要新增一系列接口和类

使用场景

  • 希望使用某个类 但是其接口与其他代码不兼容时 可以使用适配器类
  • 需要复用处于同一个继承体系 并且又有了额外的一些共同的方法 但是这些共同的方法不是所有在这一继承体系中的子类所具有的共性

Java 中使用案例

Java 核心程序库中有一些标准的适配器

  • java.util.Arrays#asList()
  • java.util.Collections#list()

识别方法 适配器可以通过以不同抽象或接口类型实例为参数的构造函数来识别 当适配器的任何方法被调用时 它会将参数转换为合适的格式 然后将调用定向到其封装对象中的一个或多个方法

posted @   伊文小哥  阅读(117)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示