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.靈活性好。this

適用場景

1.系統須要使用現有的類,而此類的接口不符合系統的須要。
2.想要創建一個能夠重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在未來引進的類一塊兒工做,這些源類不必定有一致的接口。
3.經過接口轉換,將一個類插入另外一個類系中。code

相關文章
相關標籤/搜索