设计模式-适配器模式

设计模式-适配器模式

适配器顾名思义,就是将原本不兼容的东西适配在一起,例如 MacBook 只有 type-c 接口,而我们需要一个网口插网线,就会买个转接器,这其实就是适配器的思想,通过协议转换将原本不兼容的东西变得兼容。

适配器是一种思想,可大可小。上述的例子其实就很小,有一个这样的系统,A系统市场很大,根深蒂固,对外宣称接口定义不会根据你的需求进行更改,B系统是另一个领域的市场大哥,也不会按你的需求进行更改,现在AB系统需要通信,又不想定制修改,就可以由其他厂商开发一个新项目,起适配器的作用,转换 AB 之间的协议。

如果你对 Web 容器有了解,知道 Tomcat、Jetty,它们其实都是遵循 Servlet 规范设计的,而 Servlet 规范要求传入的请求都是 ServletRequest,因此 Tomcat 的连接器中有一个 Adapter 组件,就是将譬如 HttpRequest 等转为 ServletRequest。

适配器实现

适配器模式一般有两种实现方式,基于类的和基于对象的。类适配器基于继承实现,而对象适配器基于组合实现。

基于类的实现
java 复制代码
public class Adaptee {
    public void function1() {
        System.out.println("fun1");
    }

    public void function2() {
        System.out.println("fun2");
    }

    public void functionC() {
        System.out.println("funC");
    }
}

public class Adapter extends Adaptee implements ITarget {
    @Override
    public void functionA() {
        super.function1();
    }

    @Override
    public void functionB() {
        super.function2();
    }
}

public interface ITarget {
    void functionA();

    void functionB();

    void functionC();
}

public class Main {
    public static void main(String[] args) {
        ITarget target = new Adapter();
        target.functionA();
        target.functionC();
    }
}

Adapter 类继承 Adaptee 实现了 ITarget 接口,这样可以无需重写 functionC 方法,因为二者命名和实现是一致的,适合大部分方法还是兼容,只是少量需要重写的情况。

基于对象的实现
java 复制代码
public class Adaptee {

    public void function1() {
        System.out.println("fun1");
    }

    public void function2() {
        System.out.println("fun2");
    }

    public void function3() {
        System.out.println("fun3");
    }

}

public class Adapter implements ITarget {

    private Adaptee adaptee;

    @Override
    public void functionA() {
        adaptee.function1();
    }

    @Override
    public void functionB() {
        adaptee.function2();
    }

    @Override
    public void functionC() {
        adaptee.function3();
    }
}

public interface ITarget {

    void functionA();

    void functionB();

    void functionC();

}

基于组合的实现其实与我们说的用组合代替继承的思想一致,委托给真正的执行者执行。

至于基于对象和基于类的适配器该如何选择,取决于以下方面:

  • 如果 Adaptee 接口并不多,那两种实现方式都可以
  • 如果 Adaptee 接口数量很多且与 ITarget 不一致,都需要重写,那就选择基于对象的组合实现
  • 如果 Adaptee 接口数量很多且与 ITarget 基本一致,那么就可以选择基于类的,但是要考虑接口的稳定性,如果频繁变更,那完全可以也选择组合实现
使用场景
  • 封装有缺陷的设计,例如原来的方法有漏洞但是其他系统不影响,就可以针对这个系统单独再封装一次进行适配
  • 统一多个类的接口设计,例如有三个过滤方法ABC,A的参数是 String,B的也是 String, C的是 String,String(第一个参数是要过滤的关键词,第二个是替换为什么,例如***),就可以使用适配器兼容
  • 替代依赖的外部系统,B站有一个视频利用 etcd 代替 redis,使得 redisTemplate 操作的中间件无感切换为 etcd,设计模式-适配器模式
  • 兼容老版本接口,老版本的接口依然保留,但实现切换为新版本的操作。JDK1.0 中包含一个遍历集合容器的类 Enumeration。JDK2.0 对这个类进行了重构,将它改名为 Iterator 类,并且对它的代码实现做了优化。为了做到兼容使用低版本 JDK 的老代码,暂时保留 Enumeration 类,并将其实现替换为直接调用 Itertor。
相关推荐
一叶飘零_sweeeet21 小时前
深度拆解汽车制造系统设计:用 Java + 设计模式打造高扩展性品牌 - 车型动态生成架构
java·设计模式·工厂设计模式
阿波罗尼亚1 天前
设计原则(一)Head First设计模式
设计模式
ZHE|张恒1 天前
设计模式实战篇(五):责任链模式 — 把复杂审批/过滤流程变成可组合的“传递链”
设计模式·责任链模式
CodeAmaz1 天前
使用责任链模式设计电商下单流程(Java 实战)
java·后端·设计模式·责任链模式·下单
大G的笔记本2 天前
Java常见设计模式面试题(高频)
java·开发语言·设计模式
老鼠只爱大米2 天前
Java设计模式之建造者模式(Builder)详解
java·设计模式·建造者模式·builder·23种设计模式
guangzan2 天前
常用设计模式:职责链模式
设计模式
ZHE|张恒2 天前
设计模式实战篇(二):业务逻辑“随时切换招式”——策略模式(Strategy Pattern)解析
设计模式·策略模式
小二·2 天前
设计模式面试题(14道含答案)
设计模式
老鼠只爱大米3 天前
Java 设计模式之适配器模式:系统集成的万能接口
java·设计模式·适配器模式·adapter·java设计模式