前言:設計模式
以前講過裝飾者模式,將對象包裝起來並賦予新的職責,這一章咱們也會將對象進行包裝,只不過是讓它們看起來不像本身而像是別的東西。這樣就能夠在設計中將類的接口轉化爲想要的接口,以實現同的接口,此外還將講述另外一個模式,將對象包裝起來以簡化接口。測試
真實世界的適配器好比位於美式插頭和歐式插座之間的交流電適配器。面向對象的適配器是什麼呢?this
面向對象的適配器是將一個接口轉化成另外一個接口,以符合客戶的指望。設計
例如已有的一個軟件系統,但願它能和一個新的廠商類庫搭配使用,可是這個廠商設計出來的接口不一樣於舊的接口,而你又不想改變現有的代碼,因此這個時候就須要一個適配器來完成現有系統和新的廠商類庫的對接。code
咱們在策略模式裏舉例講的鴨子。看一個簡化版的示例。對象
publicinterface Duck { void Quack();//鴨子叫 void Fly();//鴨子飛 }
publicclass MallardDuck:Duck { public void Quack() { Console.WriteLine(" Quack"); } public void Fly() { Console.WriteLine(" Fly"); } }
publicinterface Turkey { void Gobble();//咯咯叫 void Fly();//飛 } publicclass WildTurkey : Turkey { public void Gobble() { Console.WriteLine(" GobbleGobble"); } public void Fly() { Console.WriteLine(" I'm flyinga short distance "); } }
publicclass TurkeyAdapter:Duck//實現想轉換成的類型接口 { Turkey turkey; public TurkeyAdapter(Turkey turkey)//取得適配器的對象引用,並利用構造獲得這個引用 { this.turkey = turkey; } public void Quack()//實現接口中的全部方法 { turkey.Gobble(); } public void Fly() { for(var i=0;i<5;i++) turkey.Fly(); } }
MallardDuckduck = new MallardDuck(); WildTurkey turkey = newWildTurkey(); Duck turkeyAdapter = newTurkeyAdapter(turkey); Console.WriteLine(" The turkeysyas ..."); turkey.Gobble(); turkey.Fly(); Console.WriteLine(" The Ducksays ..."); turkeyAdapter.Quack(); turkeyAdapter.Fly(); Console.Read();
結果以下:繼承
客戶使用適配器的過程以下:接口
l 客戶經過目標接口調用適配器的方法對適配器發出請求。ci
l 適配器使用被適配者接口把請求轉化成被適配者的一個或多個調用接口。get
l 客戶接收到調用的結果。
適配器模式:將一個類的接口,轉化成客戶指望的另外一個接口。適配器可讓本來接口不兼容的類能夠合做無間。
該模式能夠經過建立適配器進行接口轉換,讓不兼容的接口變得兼容,讓客戶從實現的接口解耦。其類圖以下:
該適配器充滿了OO設計的原則:使用對象組合,以修改的接口包裝被適配者。被是陪者的任何子類均可以搭配着適配器使用。該模式是把客戶和接口綁定起來的,而非和實現綁定。
實際上有兩種適配器:對象適配器和類適配器。類適配器經過多重繼承來實現,而對象適配器利用組合的方式將請求傳遞給被適配者。
類適配器圖:
外觀模式:提供了一個統一的接口,用來訪問子系統的一羣接口。外觀定義了一個高層接口,讓子系統更容易使用。
外觀模式容許咱們讓客戶和子系統之間避免緊耦合。類圖以下:
最少知識原則:只和你的密友談話。
最少知識原則告訴咱們要減小對象之間的交互。該原則但願在設計時,不要讓太多的類耦合在一塊兒,省得修改系統中的一部分,會影響到其餘部分。
怎樣避免讓太多的類耦合在一塊兒呢?主要有如下的方針:
就對象而言,在該對象的方法內,咱們只應該調用屬於如下範圍的方法:
l 該對象自己
l 被當作方法的參數而傳遞進來的對象
l 此方法所建立或實例化的任何對象
l 對象的任何組件
以下示例:
(不要採用這個原則)從氣象站取得了溫度計對象,而後再從溫度計對象取得問題
Publicfloat GetTemp() { Thermometerthermometer=station.GetThermometer(); return thermometer.GetTemperature(); }
(採用這個原則)咱們在氣象站中加進一個方法,用來向溫度計請求溫度。能夠減小咱們所依賴的類的數據。
Publicfloat GetTemp() { Return station.GetTemperature(); }
l 當須要使用一個現有的類而其接口並不符合你的須要時,就須要使用適配器。
l 當須要簡化並統一一個很大的接口或者一羣負責的接口時,使用外觀。
l 適配器改變接口以符合客戶的指望。
l 外觀將客戶從一個複雜的子系統中解耦。
l 實現一個適配器的難易視目標接口的大小與複雜而定。
l 實現一個外觀,須要將子系統組合進外觀中,而後將工做委託給子系統執行。
l 適配器分爲對象適配器和類適配器,類適配器須要多重繼承。
l 能夠爲一個子系統實現一個以上的外觀。
l 適配器將一個對象包裝起來以改變其接口;裝飾者將一個對象包裝起來以增長新的行爲和責任;而外觀將一羣對象「包裝」起來以簡化其接口。