介面卡模式
是指將一個介面轉換成客戶端希望的另外一個介面,該模式使得原本不相容的類可以一起工作。
舉個例子: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.通過介面轉換,將一個類插入另一個類系中。