設計模式學習之路(五)——結構型模式之適配器模式

一、適配器模式概念

適配器模式(Adapter Pattern) :將一個接口轉換成客戶希望的另一個接口,適配器模式使接口不兼容的那些類可以一起工作,其別名爲包裝器(Wrapper)。適配器模式既可以作爲類結構型模式,也可以作爲對象結構型模式。

  • 通常情況下,客戶端可以通過目標類的接口訪問它所提供的服務。有時,現有的類可以滿足客戶類的功能需要,但是它所提供的接口不一定是客戶類所期望的,這可能是因爲現有類中方法名與目標類中定義的方法名不一致等原因所導致的。
  • 在這種情況下,將現有的接口需要轉化爲客戶類期望的接口,這樣保證了對現有類的重用。如果不進行這樣的轉化,客戶類就不能利用現有類所提供的功能,適配器模式可以完成這樣的轉化。
  • 在適配器模式中可以定義一個包裝類,包裝不兼容接口的對象,這個包裝類指的就是適配器(Adapter),它所包裝的對象就是適配者(Adaptee),即被適配的類。
  • 適配器提供客戶類需要的接口,適配器的實現就是把客戶類的請求轉化爲對適配者的相應接口的調用。也就是說:當客戶類調用適配器的方法時,在適配器類的內部將調用適配者類的方法,而這個過程對客戶類是透明的,客戶類並不直接訪問適配者類。因此,適配器可以使由於接口不兼容而不能交互的類可以一起工作。這就是適配器模式的模式動機。

二、相關實例

  1. 大姚NBA打籃球:
    姚明剛打NBA的時候有個記者問他“在CBA和NBA最大的區別是什麼?”,姚明的回答是“在NBA我需要翻譯,在CBA我不需要“。雖然後期姚明英文水平提升了,但是前期爲了和教練、球員溝通,專門給姚明配了個翻譯的。
    你看看,開始姚明要在NBA打球,不會英語怎麼交流?於是有三個辦法。第一,讓姚明學會英語,但是剛到NBA,短期內學不會英語的,這段時間怎麼溝通?第二,讓NBA教練和球員學會中文,這種方法不現實。第三,就是找個翻譯,這個翻譯就承擔了適配器的作用,將姚明聽不懂的英文轉爲聽的懂的中文。

  2. 電源適配器
    電氣學裏,有的國家用的是110V電壓,我們國家用的是220V電壓。電力傳輸的時候可能電壓升到幾千幾萬伏。而電腦手機只需要幾伏十幾伏。於是就可以用一個電源適配器,將任意伏特的電源轉爲需要的電壓,這就是電源適配器的作用。

  3. 程序接口封裝
    軟件開發設計的時候,特別是在與客戶端或外面對接時,常常會發現基礎功能都是可以的,但是對接的時候經常會發現參數類型,參數數目等不一致導致對接失敗。這時候就可以使用適配器的思想,封裝一個接口,將不適合的接口轉換成客戶端需要的接口。

    適配器就是使一個東西功能適合於另一個東西。

三、適配器模式分類

在GoF的設計模式中,對適配器模式講了兩種類型,類適配器對象適配器,由於類適配器模式通過多重繼承對一個接口與另一個接口進行匹配,而C#、VB.NET、JAVA等語言不支持多重繼承,所以不支持類適配器,只支持對象適配器。C++則兩種模式全部支持。

對象適配器結構圖

在這裏插入圖片描述

類適配器結構圖

在這裏插入圖片描述

四、代碼分析

#include<iostream>
using namespace std;

/*Target(這是客戶所期待的接口,目標可以是具體或抽象的類,也可以是接口)*/
class Target
{
public:
	Target(){}
	~Target(){}
	virtual void request(){ printf("the normal request\n"); }
};

/*Adaptee(需要適配的類)*/
class Adaptee
{
public:
	Adaptee(){}
	~Adaptee(){}
	void specialRequest(){ printf("the special request\n"); }
};

/*Adapter(通過在內部包裝一個Adaptee對象,把源接口轉化爲目標接口)*/
class Adapter :public Target
{
public:
	/*建立一個私有Adaptee對象*/
	Adapter(){ m_pAdaptee = new Adaptee; }	
	~Adapter(){}
	void request(){
	/*這樣就可以把表面上調用request()的方法變成實際調用specialRequest()*/
		m_pAdaptee->specialRequest();		
	}
private:
	Adaptee *m_pAdaptee;
};

int main()
{
	/*對客戶端而言,調用的就是Target的request()*/
	Target *tag = new  Adapter();
	tag->request();

	return 0;
}

代碼運行結果顯示:
在這裏插入圖片描述

五、何時使用適配器模式

使用適配器其實是個無奈之舉,類似與亡羊補牢的感覺。軟件開發完後期維護的時候可能因爲不同的開發人員、不同的產品、廠家而造成功能類似而接口不同的情況,這時候就是可以使用適配器了

使用適配器應該在雙方都不太容易修改的時候再使用,所以在前期設計的時候應該就避免後期適配器的使用。首先公司內部,類和方法的命名應該有規範,設計統一接口,C++可以考慮函數重載實現不同類型參數、參數數目的調用。

代碼設計的時候能預防接口不同的問題,不匹配的爲標題就不會發生;在小的接口不統一的問題發生的時候及時重構,問題不至於擴大;只有碰到無法改變原有設計和代碼的情況時,才需要考慮適配器。事後控制不如事中控制,事中控制不如事前控制,如果不論場景而盲目使用就會本末倒置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章