学了一学,设计模式-适配器模式

423 阅读3分钟

引言

设计模式,即Design Patterns,是指在软件设计中,被反复使用的一种代码设计经验。使用设计模式的目的是为了可重用代码,提高代码的可扩展性和可维护性。

显示器使用的是HDMI接口,而电脑用的是Type-c的接口。正常情况下,具备相同接口的设备才能进行连接,因此电脑是无法直接和显示器进行连接的。如果,通过接口转换器(适配器),将HDMI的接口转换成type-c的接口,便可以将电脑和显示器进行连接。

定义

结构型模式

适配器模式:通过接口转换,使得两个不兼容的接口能够在一起工作。

接口在前端可以理解为属性或者方法

模式结构

1. 目标(Target)

当前模块所期待的接口,也就是功能的使用者。

2. 适配者(Adaptee)

被访问和适配的模块提供的接口,也就是功能的提供者。

3. 适配器(Adapter)

桥接模块,消除接口的差异,使两个接口可以在一起工作。

图示:

adapt-pattern-1.png

适配器是在已存系统的情况下,为了 复用现有模块兼容接口差异 而采用的策略。

特点

优点

  1. 适配器模式符合开闭原则
  2. 适配器模式可以复用模块,减少目标模块的变动
  3. 适配器模式使目标模块和适配者模块解耦

缺点

  1. 适配器模式要求开发者熟悉适配者和目标的接口,这样开发适配器时才能覆盖所有功能。
  2. 适配器模式增加了模块的数量,增长了功能的调用链路,增加了系统的复杂度。

所以,前期架构设计时尽量考虑多样的场景,保证其扩展性稳定性,避免以后因为接口变动而导致开发人员不得已使用适配器模式。

实现

目标模块

const adaptee = new Adaptee();
class Target {
    doSomething() {
        adaptee.handleTask();
    }
}

基础模块

class Adaptee {
    handleTask() {
        // do something
    }
}

说明:目标模块的业务依赖基础模块的某个方法(接口)。之后的某一次版本,基础模块进行了大的升级,提供了增强版的api,为了保证代码的干净程度,并没有做向下兼容的处理。此时便可以使用适配器模式进行兼容。

适配者

class Adaptee {
    handleTaskNew() {
        // do something
    }
}

适配器

const adaptee = new Adaptee();
class Adapter {
    handleTask() {
        // 数据适配
        adaptee.handleTaskNew();
    }
}

目标模块

const adapter = new Adapter();
class Target {
    doSomething() {
        adapter.handleTask();
    }
}

举例

用适配器模式模拟电脑和显示器的连接。

分析:电脑(Computer)是目标模块,只接受type-c的接口,显示器(Monitor)是适配者,支持的是HDMI的接口。所以我们必须定义一个转接口(Converter),来转换HDMI接口。

显示器

class Monitor() {
    display(type, data) {
        if (type === 'HDMI') {
            console.log('显示图像', data);
        }
    }
}

转接口

class Converter() {
    monitor;
    constructor() {
        this.monitor = new Monitor();
    }
    display(type, data) {
        if (type === 'type-c') {
            let newData = this.convert(data);
            this.monitor.display('HDMI', newData);
        }
    }
}

电脑

class Computer {
    useMonitor() {
        let converter = new Converter();
        converter.display('type-c', {
            ...图像数据
        });
    }
}

电脑启动

let computer = new Computer();
computer.useMonitor();

应用场景

  1. 工具库升级时,通过适配器模式兼容历史调用
  2. 组件库变更时,通过适配器模式兼容历史使用