设计模式——适配器模式(TypeScript版)

1,073 阅读4分钟

一、定义

适配器模式(变压器模式、包装模式)是将一个类的接口变换为客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

对于适配器模式,主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。这三种明明方式是根据被适配者(src)是以怎样的形式给到Adapter来命名的。

  1. 类适配器:以类给到,在Adapter里,就是将src当做类,继承。(通过继承来实现适配器功能)
  2. 对象适配器:以对象给到,在Adapter里,将src作为一个对象,持有。(通过组合来实现适配器功能)
  3. 接口适配器:以接口给到,在Adapter里,将src作为一个接口,实现。

二、类图

目标角色(Target):定义把其他类转换为何种接口。
客户端(Client)
被适配者(Adaptee):这就是源角色。
适配器(Adapter):负责将Adaptee的接口转换为Target的接口。

类适配器通用类图

  • 对于单继承机制的语言,因为类适配器需要继承被适配者类这一缺点,因为这要求Target必须是接口,有一定局限性;
  • 被适配者的方法在Adapter中都会暴露出来,增加了使用的成本
  • 由于其继承了被适配者类,所以它可以根据需求重写被适配者类的方法,使得Adapter的灵活性增强了。

对象适配器通用类图

  • 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。根据合成复用原则, 使用组合替代继承,所以它解决了类适配器必须继承被适配者类的局限性问题,也不再要求Target必须是接口。
  • 使用成本更低、更灵活

接口适配器通用类图

当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并未该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。适用于一个接口不想使用其所有的方法的情况。

三、优点

  1. 适配器模式可以让两个没有任何关系的类在一起运行,只要这个适配器角色能够搞定就行。
  2. 增加了类的透明性,通过访问Target目标角色即可完成对源角色的访问(源角色对于客户端来说是透明的)
  3. 提高了类的复用性。源角色在原有系统中还可以正常使用,在目标角色中也可以充当新的演员。
  4. 灵活性非常好,符合开闭原则
  5. 对于类适配器模式,由于适配器类是被适配者类的子类,因此可以在适配器类中置换一些被适配者的方法,使得适配器的灵活性更强。
  6. 对于对象适配器模式,可以把多个不同的被适配者适配到同一个目标,也就是说,同一个适配器可以把被适配者类和他的子类都适配到目标接口,解决了类适配器继承被适配者类的局限性问题,也不再要求Target必须是接口。

四、缺点

  1. 类适配器模式,对于不支持多重继承的语言,一次最多只能适配一个被适配者类,而且目标抽象类只能为接口,不能为类,其使用有一定的局限性,不能将一个被适配者类和他的子类同时适配到目标接口。
  2. 类适配器模式,被适配者类的方法在Adapter中都会暴露出来,增加了使用的成本。
  3. 对象适配器模式,与类适配器模式相比,要想置换被适配者类的方法就不容易。

五、应用场景

  1. 类适配器与对象适配器的使用场景一致,就是接口不符合规范,通过适配后变成符合规范的接口进行使用;
  2. 接口适配器使用场景就是适用于一个接口不想使用其所有的方法的情况。

六、代码实现

类适配器代码实现

// 目标对象
interface Target {
    request() : void;
}
// 被适配者
class Adaptee {
    constructor() {}
    // 这是源角色,有自己的的业务逻辑
    public specificRequest() : void {}
}
// 适配器
class Adapter extends Adaptee implements Target {
    constructor() {
        super();
    }
    public request() : void {
        super.specificRequest();
    }
}

const target : Target = new Adapter();
target.request();

对象适配器代码实现

// 目标对象
interface Target {
    request() : void;
}
// 被适配者
class Adaptee {
    constructor() {}
    // 这是源角色,有自己的的业务逻辑
    public specificRequest() : void {}
}
// 适配器
class Adapter implements Target {
    private adaptee : Adaptee;
    constructor(adaptee : Adaptee) {
        this.adaptee = adaptee;
    }
    public request() : void {
        this.adaptee.specificRequest();
    }
}
// 使用
const target : Target = new Adapter(new Adaptee());
target.request();

接口适配器代码实现

interface Adaptee {
    operation1() : void;
    operation2() : void;
}

abstract class AbsAdapter implements Adaptee {
    public operation1() : void {}
    public operation2() : void {} 
}

class UseClass extends AbsAdapter {
    public operation1() : void {}// 重写该类
}

欢迎大家关注公众号