適配器模式
適配器模式是什么,你一定不難理解,因為現實中到處都是。比如說:
如果你需要在歐洲國家使用美國制造的筆記本電腦,你可能需要使用一個交流電的適配器……
當你不想改變現有的代碼,解決接口不適配問題,便可使用適配器模式,你可以寫一個類,將新廠商接口轉接成你所期望的接口。
定義適配器模式:將一個類的接口,轉換成客戶期望的另一個接口。適配器讓原本接口不兼容的類可以合作無間。
現在我們已經知道什么是適配器了,讓我們后退一步,再次看看各部分之間的關系。
類圖:
讓我們以開頭所提到的電腦電源插頭適配的問題為例:
新建一個電腦類:
1 2 3 4 5 6 7 8 9 10 11 |
|
創建一個兩孔插座接口:
1 2 3 |
|
再創建一個三孔插座類:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
創建一個適配器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
測試類
1 2 3 4 5 6 7 8 |
|
運行結果:
其他
實際上適配器模式中有“兩種”適配器:“對象”適配器和“類”適配器。
究竟什么是“類”適配器?為什么我們還沒告訴你這種適配器?因為你需要多重繼承才能夠實現它,這在Java中是不可能的。但是當你在使用多重繼承語言的時候,還是可能遇到這樣的需求。
讓我們看看多重繼承的類圖:
看起來很熟悉嗎?沒錯,唯一的差別就在于適配器繼承了Target和Adaptee。而對象適配器利用組合的方式將請求傳送給被適配者。
對象適配器和類適配器使用兩種不同的適配方法(分別是組合與繼承)。
適配器模式適用場景
- 重復使用現有的類,而此類的接口不符合系統的需要。在遺留代碼復用、類庫遷移等方面非常有用。
- 想要建立一個可以重用的類,用于與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。
- 使用第三方組件或中間件,組件接口定義和自己定義的不同,不希望修改自己的接口,但是要使用第三方組件接口的 功能,避免重復造輪子。
適配器模式優缺點
優點:
- 將目標類和適配者類解耦。
- 增加了類的透明性和復用性,將具體的實現封裝在適配者類中,對于客戶端類來說是透明的,提高了適配者的復用性。
- 靈活性和擴展性都非常好,符合開閉原則
類適配器優點:
- 由于適配器類是適配者類的子類,因此可以在適配器類中置換一些適配者的方法,使得適配器的靈活性更強。
對象適配器優點:
- 把多個不同的適配者適配到同一個目標,也就是說,同一個適配器可以把適配者類和他的子類都適配到目標接口。
缺點:
- 實現適配器所需要的工作和目標接口的大小成正比,接口越復雜適配器也越復雜。
類適配器缺點:
- 對于Java、C#等不支持多重繼承的語言,一次最多只能適配一個適配者類,而且目標抽象類只能為接口,不能為類,其使用有一定的局限性,不能將一個適配者類和他的子類同時適配到目標接口。
對象適配器的缺點:
- 與類適配器模式相比,要想置換適配者類的方法就不容易。
?
通過上一篇你已經知道適配器模式是如何將一個類的接口轉換成另一個符合客戶期望的接口的。你也知道在Java中要做到這一點,必須將一個不兼容接口的對象包裝起來,變成兼容的對象。
? 我們現在要看一個改變接口的新模式,但是它改變接口的原因是為了簡化接口,這個模式被巧妙的命名為外觀模式。它將一個或數個類的復雜的一切都隱藏在背后,只顯露出一個干凈美好的外觀。
定義
外觀模式定義:外觀模式提供了一個統一的接口,用來訪問子系統中的一群接口。外觀定義了一個高層接口,讓子系統更容易使用。
外觀模式實現了最少知識原則(Least Knowledge principle),這個原則希望不要讓太多的類耦合在一起,對用戶來說只和一個外觀類打交道了,達到客戶和一群子系統的解耦。
例題:搭建一個家庭影院系統
系統內包含設備:DVD播放器、投影機、自動屏幕、立體聲音響、爆米花機........
來看看這些組件的組成:
當你把所有設備布置好后,準備看電源時...你忘了你必須要先一個個啟用這些設備...關閉時也還將要進行一遍反向操作(崩潰....)。
結果你發現要使用你的家庭影院是那么的麻煩!
因此,我們引入外觀模式,有了外觀模式,通過實現一個更合理的接口的外觀類,你可以將一個復雜的子系統變的容易使用。看看改變之后的類圖:
定義這些媒體類:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
?
|
多媒體的具體類準備好就可以定義外觀模式類了。
外觀模式類:倆方法,一個看電影-打開一系列設備,一個電影結束-關閉一系列設備
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
測試
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
?
|
通過上面的代碼可以看出,每個類對象都要執行一些方法,如果直接new這些類創建對象去調方法會與這些類產生耦合,這時單獨再寫一個外觀類,構造初始化時拿到這些類對象,在一個方法里去調這些類對象的方法,這樣對客戶來說只和一個類打交道,與子系統的一堆類解耦了。此類原則即為:最少知識原則
最少知識原則:只和你的密友談話。
客戶端只和外觀談話,不和子設備,如DVD播放機、投影儀等談話,降低了客戶端和設備的耦合度。
下面給出最少知識原則的指導思想:
就任何對象而言,在該對象的方法內,我們只應該調用屬于以下范圍的方法:
1.該對象本身
2.被當做方法的參數而傳過來的對象
3.該方法所創建或實例化的任何對象
4.對象的任何組件
盡可能自己封裝子設備的方法,以便減少客戶端和子設備的耦合。
外觀模式優點
松耦合:使客戶端與子系統之間解耦,讓子系統內部的模塊功能更容易擴展與維護。
簡單易用:客戶端無需了解子系統的內部實現及內部構成,只需要與外觀類交互即可。
更好地劃分訪問層次:部分方法對外,部分方法對內交互使用。子系統將暴露在外的功能集中到外觀類中可以隱藏子系統內部細節。
適配器、裝飾者、外觀模式對比
- 在介紹裝飾者模式時,引出了一個開閉原則,即對修改關閉,對擴展開放。裝飾者模式主要強調的是在不改變原有類的基礎上,添加新功能。
- 適配器模式主要是對適配對象進行調整,以便適合消費者的需求。從而達到消費者和被適配者解耦的目的。
- 外觀模式的特點主要是簡化接口,以及減少客戶端對外觀組件的耦合。因為如果客戶端變化來,組件的子系統變化了,不用影響客戶端。除此之外,在封裝組件時,適當的在外觀類中添加一些自己想要的規則。如上面例子中各設備的開關順序
總結
- 當需要使用一個現有的類,而其接口并不符合你的需要時,就使用適配器。
- 當需要簡化并統一一個很大的接口或者一群復雜的接口時,使用外觀。
- 適配器改變接口以符合客戶的希望
- 外觀將一個客戶從復雜的子系統中解耦。
- 實現一個適配器可能需要一番功夫,也可能不費工夫,視目標接口的大小與復雜度而定。
- 實現一個外觀,需要將子系統組合進外觀中,然后將工作委托給子系統執行。
- 適配器模式有兩種形式,對象適配器和類適配器。類適配器需要用到多重繼承。
- 你可以為一個子系統實現一個以上的外觀。
- 適配器將一個對象包裝起來以改變其接口;裝飾器將一個對象包裝起來以增加新的行為和責任,而外觀將一群對象包裝起來以簡化其接口。