JS 设计模式 十(适配器模式)

适配器模式

是指将一个接口转换成客户端希望的另外一个接口,该模式使得原本不兼容的类可以一起工作。
举个例子:macbook pro有一个HDMI接口,一条HDMI接口的数据线,现在要外接显示器,而显示器只有VGI接口,我们需要一个HDMI-VGI转换器,这个转换器其实起到的作用就是适配器,让两个不兼容的接口可以一起工作。

适配器有4种角色:

1.目标抽象角色(Target):定义客户所期待的使用接口。(VGI接口)
2.源角色(Adaptee):需要被适配的接口。(HDMI接口)
3.适配器角色(Adapter):把源接口转换成符合要求的目标接口的设备。(HDMI-VGI转换器)
4.客户端(client):例子中指的VGI接口显示器。

实例

假设有两种充电接口MicroUSB和USBTypec

function ChargingCord(name) {
  var _name = name || '默认:无接口'
  this.work = function () {
    console.log('使用' + _name + '接口');
  }
  this.getName = function () {
    return _name;
  }
  this.check = function (target) {
    return _name == target.getName();
  }
}

function MicroUSB() {
  this.__proto__ = new ChargingCord('MicroUSB');
}

function USBTypec() {
  this.__proto__ = new ChargingCord('USBTypec');
}

有两种车分别有不同的充电接口

function Car(name, chargingCord) {
  var _name = name || '默认:车'
  var _chargingCord = chargingCord || new ChargingCord();
  this.getName = function () {
    return _name;
  };
  this.charge = function (target) {
    if (_chargingCord.check(target.getChargingCord())) {
      console.log(this.getName());
      _chargingCord.work();
      console.log('充电');
      target.charging();
    }
    else {
      console.log(this.getName()+"的"+_chargingCord.getName());
      console.log(target.getName()+"的"+target.getChargingCord().getName());
      console.log('接口不对无法充电');
    }
  }
}    
function Porsche911() {
  this.__proto__ = new Car('Porsche911', new USBTypec());
}    
function Porsche781() {
  this.__proto__ = new Car('Porsche781', new MicroUSB());
}

有两种手机有不同的接受充电的接口

function Phone(name, chargingCord) {
  var _name = name || '默认:手机'
  var _chargingCord = chargingCord || new ChargingCord();
  this.getChargingCord = function () {
    return _chargingCord;
  };
  this.getName = function () {
    return _name;
  };
  this.charging = function () {
    console.log(_name);
    _chargingCord.work();
    console.log('接收');
  }
}    
function IPhone() {
  this.__proto__ = new Phone('IPhone', new USBTypec());
}    
function MIPhone() {
  this.__proto__ = new Phone('MIPhone', new MicroUSB());
}

我们分别用辆车个两种手机充电

var porsche911 = new Porsche911();
var porsche781 = new Porsche781();    
var iPhone = new IPhone();
var miPhone = new MIPhone();    
console.log('-----------------------------------------');
porsche911.charge(iPhone);
console.log('-----------------------------------------');
porsche781.charge(miPhone);
console.log('-----------------------------------------');
porsche781.charge(iPhone);
console.log('-----------------------------------------');

结果

-----------------------------------------
Porsche911
使用USBTypec接口
充电
IPhone
使用USBTypec接口
接收
-----------------------------------------
Porsche781
使用MicroUSB接口
充电
MIPhone
使用MicroUSB接口
接收
-----------------------------------------
Porsche781的MicroUSB
IPhone的USBTypec
接口不对无法充电
-----------------------------------------
Porsche911的USBTypec
MIPhone的MicroUSB
接口不对无法充电
-----------------------------------------

所以我们要创建适配器函数

function PhoneUSBTypecToMicroUSB(Phone) {
  var _USBTypec = new ChargingCord('USBTypec');
  var _MicroUSB = new ChargingCord('MicroUSB');
  if (_USBTypec.check(Phone.getChargingCord())) {
    Phone.charging = function () {
      console.log(this.getName());
      _USBTypec.work();
      console.log('转接');
      _MicroUSB.work();
      console.log('接收');
    }
    Phone.getChargingCord = function () {
      return _MicroUSB;
    };
    return Phone;
  }
  else {
    console.log('接口不对无法转换');
  }
}

function PhoneMicroUSBToUSBTypec(Phone) {
  var _USBTypec = new ChargingCord('USBTypec');
  var _MicroUSB = new ChargingCord('MicroUSB');
  if (_MicroUSB.check(Phone.getChargingCord())) {
    Phone.charging = function () {
      console.log(this.getName());
      _MicroUSB.work();
      console.log('转接');
      _USBTypec.work();
      console.log('接收');
    }
    Phone.getChargingCord = function () {
      return _USBTypec;
    };
    return Phone;
  }
  else {
    console.log('接口不对无法转换');
  }
}

function PhoneDeleteInterface(Phone){
  delete Phone.charging;
  delete Phone.getChargingCord;
  return Phone;
}

再来测试接口转换和充电情况

PhoneMicroUSBToUSBTypec(iPhone);
console.log('-----------------------------------------');
PhoneUSBTypecToMicroUSB(miPhone);
console.log('-----------------------------------------');
porsche781.charge(PhoneUSBTypecToMicroUSB(iPhone));
console.log('-----------------------------------------');
porsche911.charge(PhoneMicroUSBToUSBTypec(miPhone));
console.log('-----------------------------------------');
porsche781.charge(PhoneDeleteInterface(iPhone));
console.log('-----------------------------------------');
porsche911.charge(PhoneDeleteInterface(miPhone));

适配后结果

接口不对无法转换
-----------------------------------------
接口不对无法转换
-----------------------------------------
Porsche781
使用MicroUSB接口
充电
IPhone
使用USBTypec接口
转接
使用MicroUSB接口
接收
-----------------------------------------
Porsche911
使用USBTypec接口
充电
MIPhone
使用MicroUSB接口
转接
使用USBTypec接口
接收
-----------------------------------------
Porsche781的MicroUSB
IPhone的USBTypec
接口不对无法充电
-----------------------------------------
Porsche911的USBTypec
MIPhone的MicroUSB
接口不对无法充电

适配器模式优点

1.可以让任何两个没有关联的类一起运行。
2.提高了类的复用。
3.增加了类的透明度。
4.灵活性好。

适用场景

1.系统需要使用现有的类,而此类的接口不符合系统的需要。
2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
3.通过接口转换,将一个类插入另一个类系中。

你可能感兴趣的:(javascript,design-pattern,适配器模式)