“接口隔離”模式
- 在元件建構過程中,某些接口之間直接的依賴常常會帶來很多問題、甚至根本無法實作。采用添加一層間接(穩定)接口,來隔離本來互相緊密關聯的接口是一種常見的解決方案。
- 典型模式
- Facade
- Proxy
- Adapter
- Mediator
動機(Motivation)
- 在軟體系統中,由于應用環境的變化,常常需要将“一些現存的對象”放在新的環境中應用,但是新環境要求的接口是這些現存對象所不滿足的。
- 如何應對這種“遷移的變化"?如何既能利用現有對象的良好實作,同時又能滿足新的應用環境所要求的接口?
模式定義
将一個類的接口轉換成客戶希望的另一個接口。Adapter模式使得原本由于接口不相容而不能一起工作的那些類可以一起工作。—《設計模式》GoF
類圖
示例
對象擴充卡:
#include <iostream>
using namespace std;
//目标接口(新接口)
class ITarget {
public:
virtual void process() = 0;
};
//遺留接口(老接口)
class IAdaptee {
public:
virtual void foo(int data) = 0;
virtual int bar() = 0;
};
//遺留類型
class OldClass : public IAdaptee {
//....
public:
virtual void foo(int data)
{
cout << "OldClass:" << data << endl;
}
virtual int bar()
{
return 100;
}
};
//對象擴充卡
class Adapter : public ITarget { //繼承
protected:
IAdaptee* pAdaptee;//組合 對象擴充卡
public:
Adapter(IAdaptee* pAdaptee) {
this->pAdaptee = pAdaptee;
}
// 新街口
virtual void process() override {
int data = pAdaptee->bar();
pAdaptee->foo(data);
}
};
int main() {
IAdaptee* pAdaptee = new OldClass();
ITarget* pTarget = new Adapter(pAdaptee);
pTarget->process();
getchar();
return 0;
}
輸出:
OldClass:100
類擴充卡(繼承的方式):
不是太好,有很多其他的問題。 OldClass 定死了,沒靈活性。類擴充卡隻有壞處沒有好處。現在用的很少了。
//類擴充卡
class Adapter : public ITarget,
protected OldClass //多繼承
{
};
要點總結
- Adapter模式主要應用于“希望複用一些現存的類,但是接口又與複用環境要求不一緻的情況”,在遺留代碼複用、類庫遷移等方面非常有用。
- GoF23定義了兩種Adapter模式的實作結構:對象擴充卡和類擴充卡。但類擴充卡采用“多繼承”的實作方式,一般不推薦使用。對象擴充卡采用“對象組合”的方式,更符合松耦合精神。
- Adapter模式可以實作的非常靈活,不必拘泥于Gof23中定義的兩種結構。例如,完全可以将Adapter模式中的“現存對象”作為新的接口方法參數,來達到适配的目的。