適配器模式


一:生活中一些實例?
???? 簡單說現在家庭中使用的電器一般要求電壓是220V的,但是有的電器使用要求的電壓是110V,怎么辦呢?我們直接在110V電壓電器上直接安裝一個變壓器這樣不就行了嗎?這樣我們不就可以使用110V電壓的電器了嗎?
??? 相信很多人都知道恒大足球隊吧,他們隊里有一些外援,他們語言不同,他們是怎么交流了,按照我們想,讓對內的球員都會說中文不就好了。這樣對內的交流問題不就解決了。

二:上面實現功能中會出現什么問題呢?
???? 如果使用電器中出現其他電壓電器,或者有很多110V電壓的電器,我們就需要每次都添加一個變壓器,給沒有這個轉換電壓功能,每一次都需要添加一次方法。這樣做的,每一次都需要我們去添加方法,修改里面原代碼,這樣做違反開閉原則,那么我們要如何做呢?我們可以在外面是先一個接口,然后將轉化方法放在里面,我們需要時候就去調用,這樣不是會很方便。
??? 同樣的如果隊里球員都學習中文,第一不說中文學期很難,第二學習也很占用時間,這樣會影響球員的休息還有訓練。但是如果我們給球員帶一個翻譯器呢?是不是這樣問題就解決了呢?

三:再設計模式中:適配器模式
在適配器模式中如何解決電壓問題呢?
?? 創建接口:


定義變壓器類:


定義改變適配器的類:


定義變壓器地輸出110V:


定義輸出220V電壓類:


這樣我們就在原有類的基礎上,實現調用,也解決每次都需要添加麻煩。也讓兩個不能在一起工作在一起工作。


四:適配器模式定義:
適配器模式(Adapter):就是把一個類的接口轉換成客戶所期待的另一種接口。Adapter使得原本由于接口不兼容而不能在一起工作的那些類可以在一起工作。

一) 適配器模式的結構
?????? 適配器模式有類的適配器模式和對象的適配器模式兩種不同的形式。
?????? 類適配器通過繼承,是靜態的定義方式。
?????? 對象適配器通過代理,是動態組合的方式。
類適配器模式
?????? 類適配器模式把適配的類API轉換成目標類的API



??? 從圖中可以看出Adaptee中沒有sampleOperation2()方法,而客戶端則期待這個方法。為了使客戶端能夠使用這個Apaptee類,所以提供一個中間環節,即類Adapter,也就是這個類把Adaptee與Target類銜接起來。Adapter與Apaptee是繼承關系,這就決定是類適配器模式。


模式中角色:


?目標(Target) 角色:目標角色,期待得到的接口。


?源(Adapee)角色: 適配者角色,現在需要適配的接口。


?適配器(Adapter)角色:適配器角色,適配器類是本模式核心。適配器把源接口轉換成目標接口。顯然這一角色不可能是接口,而必須是具體類。


代碼樣例:


目標角色:

源(Adapee)角色:

適配器角色Adapter:

對象適配器模式
與類的適配器模式一樣,對像的適配器模式把被適配器的類的API轉換成目標類的API,與類適配器不同的是,對象適配器模式不使用繼承關系連接到Adaptee類,使用了委派關系連接到了Adaptee類。

從圖中可以看出Adaptee類中沒有sampleOperation2()方法,客戶端是期待這個方法的。為了使客戶端能夠使用Adaptee類,我們需要提供一個包裝(Wrapper類)Adapter。這個包裝類包裝一個Adatee的實例,從而能使的包裝類能把Adaptee的API與Target類的API銜接起來。Adater與Adaptee是委派關系,這就決定是對象適配器模式
目標角色:

源角色:

適配器角色:

我們了解適配器模式,那么我們看看實際項目中我們應當怎么使用呢?
例如公司購買了一個驗證客戶信息的離架產品類InfoValidation,但是賣方沒有提供源碼。此類只提供用于檢查客戶輸入的信息,包含驗證姓名、地址、電話區號、手機號等功能。現在公司需要增加一個驗證社會安全號(SSN)的功能,這里我們不就可以使用類適配器來做嗎?這里我們首先想一下類適配器結構,然后來構建這里所要實現結構。

結構部分:


下面是我們代碼實現部分:
根據我們以上結構來一步一步實現我們代碼部分:這樣就會非常簡單
首先編寫接口部分:
public interface CusInfoValidator {

?public abstract boolean isValidName(String name);
?public abstract boolean isValidAddress(String address);
?public abstract boolean isValidZipCode(String zipCode);
?public abstract boolean isValidCellPhoneNum(String phoneNum);
?public abstract boolean isValidSSNNum(String SSNNum);
}
是不是跟我們結構一樣的

接下來我們再來編寫所繼承類InfoValidation類(被適配器類)
Class InfoValidation? {

??? public abstract boolean isValidName(String name)? {
??????? boolean isValid=true;
???? String ns = name.trim();
???? String nStr = ns.replaceAll("\\b\\s{1,}\\b", "");
???? int len = nStr.length();

???? System.out.println("******Length = " + len);

???? if(len != 0 ){
??????? for(int m=0; m<len; m++){
?????????? if(Character.isDigit(nStr.charAt(m))==true)
????????????? isValid=false;
??????? }
??????? return isValid;
??????? }
??????? else{
??????? return false;
???? }
??? }
?public abstract boolean isValidAddress(String address){代碼省略}
?public abstract boolean isValidZipCode(String zipCode){代碼省略}
?public abstract boolean isValidCellPhoneNum(String phoneNum){代碼省略}
}

實現我們適配器代碼:
class InformationAdapter extends InfoValidation implements CusInfoValidator{
??? public boolean isValidSSNNum(String SSNNum){
??? boolean isValid=true;
?????? String ns = SSNNum.trim();
??? String nStr = ns.replaceAll("\\s{1,}", "");
??? int len = nStr.length();

??? if ( (nStr.charAt(3) == '-') && (nStr.charAt(6) == '-') && (len==11) ) {
?????? for(int m=0; m<len; m++){
?????? if(? (m != 3) && (m !=6) && ( Character.isDigit(nStr.charAt(m))==false) ){
????????? isValid=false;
?????? }
?????? }
?????? return isValid;
??? }
??? else{
??? return false;
??? }
?}
}

這樣我們就在原有功能上添加一個社會安全號SSN驗證功能。通過這個實例,可能就會有會問:“適配器模式是不是就是給源角色增加新的方法!”,這樣說也對但是不全面。
在適配器模式定義中主要講的是讓接口變換成客戶端所期待一種接口,也就是說‘適配器模式’可以用于增加新的方法,但主要還是轉換接口。例如下面一般是我們人物信息例子:


上面結構途中在Person類中是沒有getDepartment() 方法,在適配器改變Person類構造函數的參數,添加了demartment參數,適配器是改變是接口。我們這個設計目的不是增加方法,而是改變接口。

五: 我們又該怎么權衡類配置器和對象適配器呢,它們又有什么特點呢?
??? 在上面我們寫到類適配器是適用對象繼承的方式,是靜態的方式,而對象適配使用時對象組合方式,是動態組合方式。
??? 對于類適配器,由于適配器直接繼承了Adaptee,使得適配器不能和Adaptee的子類一起工作,因為繼承是靜態的關系,當適配器繼承了Adaptee后,就不可能再去處理? Adaptee的子類了。
   對于對象適配器,一個適配器可以把多種不同的源適配到同一個目標。換言之,同一個適配器可以把源類和它的子類都適配到目標接口。因為對象適配器采用的是對象組合的關系,只要對象類型正確,是不是子類都無所謂。
 ? 對于類適配器,適配器可以重定義Adaptee的部分行為,相當于子類覆蓋父類的部分實現方法。
  對于對象適配器,要重定義Adaptee的行為比較困難,這種情況下,需要定義Adaptee的子類來實現重定義,然后讓適配器組合子類。雖然重定義Adaptee的行為比較困難,但是想要增加一些新的行為則方便的很,而且新增加的行為可同時適用于所有的源。
 對于類適配器,僅僅引入了一個對象,并不需要額外的引用來間接得到Adaptee。
 對于對象適配器,需要額外的引用來間接得到Adaptee。
建議盡量使用對象適配器的實現方式,多用合成/聚合、少用繼承。當然,具體問題具體分析,根據需要來選用實現方式,最適合的才是最好的。

六:那么又有哪些適配器模式的又有哪些優缺點呢?
優點:
?? 1.將目標類和適配者類解耦,通過一入一個適配器類來重用現有的適配者類,而無需要修改原有代碼。
?? 2.增加了類的透明度和復用性,將具體的實現封裝在適配者類中,對于客戶端類來說是透明的,而且提高了適配者的復用性。
?? 3.靈活性和擴展性都非常好,通過使用配置文件可以很方便的更換適配器,也可以在不修改原有代碼基礎上增加新的適配器類,完全符合“開閉原則”。
缺點:
過多的使用適配器,會讓系統非常零亂,不易整體進行把握。比如,明明看到調用的是A接口,其實內部被適配成了B接口的實現,一個系統如果太多出現這種情況,無異于一場災難。因此如果不是很有必要,可以不使用適配器,而是直接對系統進行重構。

七:我們又該怎樣使用適配器呢?
? 使用場景:
?1).系統中需要使用現有類,而這個類接口不符合系統的需要,也就是不兼容
?2).想要建立一個可重復使用的類,用于關聯彼此沒有太大聯系的一些類
?3).需要一個統一的輸出接口,而輸入端類型不確定

八:適配器模式總結
??? 適配器模式可以重用一個現有的類,滿足客戶需求,將客戶端的調用轉化為現有方法調用。
??? 類適配器:客戶端的需求通過接口表達出來,可以創建一個實現該接口的適配類,適配類同時還要繼承現有類。
??? 對象適配器:客戶端沒有指定接口,創建一個新的適配器類,實現繼承客戶端類,在該類中維護一個現有的類實例對象作為成員變量。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容