专栏名称: 蚂蚁金服ProtoTeam
数据前端团队
目录
相关文章推荐
51好读  ›  专栏  ›  蚂蚁金服ProtoTeam

Typescript玩转设计模式 之 结构型模式(上)

蚂蚁金服ProtoTeam  · 掘金  · 前端  · 2017-12-10 11:26

正文

请到「今天看啥」查看全文


); super.iphoneInterface(); } } function commonAdapterDemo () { const computer1 = new HuaweiDataWireAdapter(); computer1.usb(); const computer2 = new IphoneDataWireAdapter(); computer2.usb(); } commonAdapterDemo();

适用场景

  • 你想使用一个已经存在的类,而他的接口不符合你的需求;
  • 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作;
  • (仅对于对象适配器)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口。对象适配器可以适配他的父类接口;

优点

  • 将目标类和被适配类解耦,通过引入一个适配器类来重用现有的被适配类,而无须修改原有代码;
  • 增加了类的透明性和复用性,将具体的实现封装在被适配类中,对于客户端类来说是透明的,而且提高了被适配类的复用性;
  • 类适配器:由于适配器类是被适配类的子类,因此可以在适配器类中置换一些被适配类的方法,使得适配器的灵活性更强;
  • 对象适配器:一个对象适配器可以把多个不同的被适配类适配到同一个目标,也就是说,同一个适配器可以把被适配类和它的子类都适配到目标接口;

缺点

  • 类适配器:单继承机制使得同时只能适配一个被适配类;
  • 对象适配器:与类适配器模式相比,要想置换被适配类的方法就不容易;

相关模式

  • 桥接(Bridge)模式的结构与对象适配器类似,但桥接模式的出发点不同:桥接目的是将接口部分和实现部分分离,从而使他们可以较为容易也相对独立的加以改变。而适配器则意味着改变一个已有对象的接口。
  • 装饰器(Decorator)模式增强了其他对象的功能而同时又不改变他的接口。因此装饰器对应用程序的透明性比适配器要好。装饰器支持递归组合,而纯粹使用适配器是不可能实现这一点的。
  • 代理(Proxy)模式在不改变他的接口的条件下,为另一个对象定义了一个代理。

桥接(Bridge)

定义

将抽象部分与他的实现部分分离,使他们都可以独立地变化。

结构

桥接模式包含以下角色:

  • Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象,它与Implementor之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。
  • RefinedAbstraction(扩充抽象类):扩充由Abstraction定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
  • Implementor(实现类接口):定义实现类的接口,这个接口不一定要与Abstraction的接口完全一致,事实上这两个接口可以完全不同,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而具体实现交给其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来替代继承关系。
  • ConcreteImplementor(具体实现类):具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplementor对象将替换其父类对象,提供给抽象类具体的业务操作方法。

示例

// 汽车是一个维度,有多种不同的车型
abstract class AbstractCar {
  abstract run(): void;
}

// 路是一个维度,有多种不同的路
abstract class AbstractRoad {
  car: AbstractCar;
  abstract snapshot(): void;
}

/**
 * 汽车和路两个维度
 * 桥接就是一个维度的类中引用了另一个维度的对象,但只关心接口不关心是哪个具体的类
 * 从而实现两个维度独立变化
 */
class SpeedRoad extends AbstractRoad {
  constructor(car: AbstractCar) {
    super();
    this.car = car;
  }
  snapshot(): void {
    console.log('在高速公路上');
    this.car.run();
  }
}

class Street extends AbstractRoad {
  constructor(car: AbstractCar) {
    super();
    this.car = car;
  }
  snapshot(): void {
    console.log('在市区街道上');
    this.car.run();
  }
}

class Car extends AbstractCar {
  run(): void {
    console.log('开着小汽车'






请到「今天看啥」查看全文