设计模式-适配器模式

设计模式-适配器模式

适配器顾名思义,就是将原本不兼容的东西适配在一起,例如 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。
相关推荐
fakerth20 小时前
【OpenHarmony】设计模式模块详解
c++·单例模式·设计模式·openharmony
alibli1 天前
一文学会设计模式之创建型模式及最佳实现
c++·设计模式
1024肥宅1 天前
前端常用模式:提升代码质量的四大核心模式
前端·javascript·设计模式
郝学胜-神的一滴1 天前
设计模式依赖于多态特性
java·开发语言·c++·python·程序人生·设计模式·软件工程
帅次1 天前
系统分析师:软件需求工程的软件需求概述、需求获取、需求分析
设计模式·重构·软件工程·团队开发·软件构建·需求分析·规格说明书
EXtreme351 天前
【数据结构】算法艺术:如何用两个栈(LIFO)优雅地模拟队列(FIFO)?
c语言·数据结构·算法·设计模式·栈与队列·摊还分析·算法艺术
1024肥宅2 天前
JavaScript常用设计模式完整指南
前端·javascript·设计模式
特立独行的猫a2 天前
C++观察者模式设计及实现:玩转设计模式的发布-订阅机制
c++·观察者模式·设计模式
better_liang2 天前
每日Java面试场景题知识点之-单例模式
java·单例模式·设计模式·面试·企业级开发
sg_knight2 天前
什么是设计模式?为什么 Python 也需要设计模式
开发语言·python·设计模式