設計模式學習之Facade模式
今天講外觀模式,這個模式其實理解起來超級簡單,為什么呢?這個模式其實我覺得可以用四個字來形容它:化繁為簡。因為這個模式就是用來提供簡化接口的。什么是簡化接口?其實就是將很多復雜的接口組合起來成為一個新接口。你或許會問,把許多復雜的接口組合起來不是會更復雜嗎,怎么會變得簡單,這不是自相矛盾嗎?哈哈,那你就錯了,其實外觀模式更像一個東西:宏。又拿宏說事兒了,不是上次命令模式里面提到過“命令宏”的嗎,這個模式和宏有什么關系呢?嘿嘿,如果把上次“命令宏”稱為“狹義的宏”的話,那么外觀模式就是“廣義的宏”(似乎越來越難理解了……)。
別急,讓我慢慢道來,先解決為什么叫“廣義的宏”這個問題。首先,廣義代表這個模式具有很高的通用性,也就是說,它不只是限于對單一類型的接口進行“捆綁銷售”,它還能對不同類型的接口進行“集中甩賣”,哎,說的專業點,就是外觀模式可以將不同子系統的接口組合成一個接口供用戶使用,而這個接口因為組合了很多的功能,使得用戶不用自己去定義n多的子系統,然后自己手動操作這些子系統的方法,而只需要調用這個合成的接口就能完成一大堆的功能,是不是簡化了呢?
再來詳細講一下吧,定義還是必須的:
- 外觀模式:
為子系統中的一組接口提供一個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。 - 適用性:
- 當你要為一個復雜子系統提供一個簡單接口時。子系統往往因為不斷演化而變得越來越復雜。大多數模式使用時都會產生更多更小的類。這使得子系統更具可重用性,也更容易對子系統進行定制,但這也給那些不需要定制子系統的用戶帶來一些使用上的困難。Facade 可以提供一個簡單的缺省視圖,這一視圖對大多數用戶來說已經足夠,而那些需要更多的可定制性的用戶可以越過facade層。
- 客戶程序與抽象類的實現部分之間存在著很大的依賴性。引入facade將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。
- 當你需要構建一個層次結構的子系統時,使用facade模式定義子系統中每層的入口點。如果子系統之間是相互依賴的,你可以讓它們僅通過facade進行通訊,從而簡化了它們之間的依賴關系。
再上類圖:
對這類圖是不是有點無語?是不是感覺摸不著頭腦?呵呵,別被它的外表所嚇倒,其實你只需要關心最上面的那個接口就行了,對于subsystem也就是子系統可以完全不需要仔細的考慮,而只需要知道如何調用子系統提供的接口就行了,我們還是用個例子來說吧:
就拿開車來說,開車是需要很多的操作的,很多小細節啊(這可是學駕照時的親身體會啊),我們簡單說一下:開車門->插鑰匙->啟動發動機->踩離合器->進檔->松離合器->松手剎->加油門->轉動方向盤...(車跑起來了,哈哈,不過后序步驟就要靠你自己了;))。但隨著科技的發展,現在果斷出現了全自動的汽車(科技真給力),對于這種全自動的汽車來說,顯然沒有了人,這些操作就只能又計算機控制了,如果現在要你寫一個這樣的全自動駕車的程序,使得用戶只需要插入鑰匙,點擊開車按鈕就能自動開車了(這就方便了,每個人都會),那該怎么寫呢?
是不是覺得很復雜?沒關系,讓復雜的問題交給科學家吧,咱們要懂得利用他們的成果,嘻嘻,假設科學家們已經將復雜的控制功能封裝好了,成為了一個個子系統,比如車門,檔位,發動機,離合器,手剎,油門都有了各自的控制方法,那我們現在就只需要寫汽車的接口,就三個:權限認證(插鑰匙,當然現在科技這么發達,也有可能出現別的驗證方式呢),還有開車,停車,怎么做呢:
//汽車的接口 public interface ICar { public bool auth(); public void drive(); public void stop(); }
如前所述,現在科學家提供了很多的控制類接口:
//車門接口 public interface ICarDoor { public void open(); public void close(); } //檔位接口 public interface IGears { public void setLevel(int level); } //轉向燈接口 public interface ITurnLight { //0為左,1為右 public void setLight(int direction); } //喇叭接口 public interface ISpeaker { public void beep(); } //引擎接口 public interface IEngine { public void open(); public void close(); public void refuel(); } //離合器接口 public interface IClutch { public void press(); public void loose(); } //手剎接口 public interface IHandBrake { public void pull(); public void loose(); } //油門接口 public interface IAccelerator { public void accelerate(int level); } //方向盤 public interface IWheel { public void toLeft(int degree); public void toRight(int degree); } //權限認證(插鑰匙,當然現在科技這么發達,也有可能出現別的驗證方式呢), public interface IAuthSystem { public bool auth(); }
既然已經有了這么多接口,那么我們的自動系統就只需要根據這些接口進行順序的調用就可以了:
public class AutoCar implements ICar { ICarDoor carDoor; IGears gears; ITurnLight turnLight; ISpeaker speaker; IEngine engine; IClutch clutch; IHandBrake handBrake; IAccelerator accelerator; IWheel wheel; public AutoCar(ICarDoor carDoor, IGears gears, ITurnLight turnLight, ISpeaker speaker, IEngine engine, IClutch clutch, IHandBrake handBrake, IAccelerator accelerator, IWheel wheel, IAuthSystem authSystem) { this.carDoor=carDoor; this.gears=gears; this.turnLight=turnLight; this.speaker=speaker; this.engine=engine; this.clutch=clutch; this.handBrake=handBrake; this.accelerator=accelerator; this.wheel=wheel; this.authSystem=authSystem; } public void drive() { carDoor.close();//關門都由系統來做,人真懶啊,:) if(authSystem.auth())//驗證權限 { engine.open();//打開發動機 clutch.press();//踩死離合器 gears.setLevel(1);//進1檔 turnLight.setLight(0);//開左轉向燈 speaker.beep();//鳴笛 clutch.loose();//松開離合器 handBrake.loose();//松手剎 accelerator.accelerate(1);//加一點就行了,別過猛了,不然會很暴力的,:) //后面的事交給科學家吧,:) } } public void stop(); }
這樣一來,用戶只需要關心ICar接口就行了,想想當你想出門的時候,只需要打開車門,插入鑰匙,然后按“開車”按鈕,然后什么都不用管,那將是多么的愜意啊,其實,這一切都得感謝外觀模式啊,外觀模式就是提供一個非常友好的外觀給用戶(長得漂亮誰不喜歡啊:)),使得用戶不需要關心它內部的實現細節,使用戶從繁重的工作中解脫出來。
唉,這上面就是外觀模式?不就是把一堆類集合在一起,然后把需要的不同類的方法集中到一個方法里面實現嗎,這么簡單?是啊,就這么簡單!多簡單啊!我想現在你應該搞清楚為什么我把外觀模式叫做廣義的宏了吧,不信你再看看上面的代碼,Car類中的drive()方法不就是個典型的宏嗎,如果你還不清楚,請深入的學一下office word,:)
好了,這個模式就講到這里,但順便提一下另外幾個模式:裝飾者模式和適配器模式,難道這三個模式有什么共同點嗎?是的,它們的共同點就是:對接口進行再次封裝。裝飾者模式是將被裝飾者的接口動態的加上新的職責,適配器模式是將被適配者的接口轉換成新的接口,而外觀模式則是組合多個系統的接口創造新的接口。各種模式都有各自獨特的作用,要看你怎么用了。
作者:everdom
出處:http://everdom.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利。


浙公網安備 33010602011771號