Facade模式在開發中使用的頻率非常高,比如我們在使用一些第三方SDK庫的時候,他們基本都是使用了外觀模式。
外觀模式非常簡單,就是在我們功能具體實現的類上面建立一個統一的類來讓客戶端使用,而不用暴露具體每個類的細節。
定義:
要求一個子系統外部和內部的通訊通過一個統一的對象來進行,提供了一個高層次的接口,使得子系統更加易用。
使用場景:
1.為一個復雜的子系統提供一個簡單的接口。子系統往往會不斷演化,而變得復雜、多變。
外觀模式隱藏了子系統的細節,我們只要關心統一個接口類就行了,隱藏了子系統的具體實現,隔離了變化。
2.當需要構建一個層次結構的子系統時,可以讓子系統通過Facade通信,從而簡化了他們之間的依賴關系。
實現:
比如現在的智能手機有很多功能,拍照,電話,運行軟件,短信等。
我們以拍照和電話為例子。
有兩個系統類,PhoneImpl和CameraImpl
PhoneImpl中有dail,hangup方法
CameraImpl有open、takePicture、takeVedio方法
如果我們要去視頻通話的時候,就需要用到PhoneImpl.dail和CameraImpl.open、CameraImpl.takeVedio方法,讓客戶端來操作的話會很麻煩。
于是我們使用一個外觀類MobilePhone,里面有一個VedioChat方法,方法調用了PhoneImpl.dail和CameraImpl.open、CameraImpl.takeVedio,客戶端只要去使用MobilePhone中的VedioChat方法就行了。
Android中的實現
我們在使用Activity的時候,常常用到startActivity、sendBroadcast、getResources、getPackageManager等類似的方法,其實這里Activity更像是一個代理類,這些方法內部是調用了mBase.xxxXX方法,這里的mBase就是context的具體實現ContextImpl類對象。
而ContextImpl類里面對這些方法的具體實現其實也不是自身實現的,就比如startActivity方法,其實是調用了mMainThread.getInstrumentation().exeStartActivity。
所以這里的ContextImpl類其實就是一個外觀類,他本身并沒有實現具體的方法,而是保存了很多子系統對象,當用戶調用一個方法時,其實是調用了這些子系統對象的方法。
這樣使得用戶不用去關心具體是那個對象實現了哪些方法,使用更為便捷了。
再來舉幾個里面方法的例子:
sendBroadcast其實是調用了:
ActivityManagerNative.getDefault().broadcastIntent
registerReceiverInternal調用了:
ActivityManagerNative.getDefault().registerReveiver
startService調用了:
ActivityManagerNative.getDefault()。
setWallpaper調用了
getWallpaperManager().setBitmap(bitmap)
優點:
1.對客戶端隱藏了子細節,減少了客戶端對于子系統的耦合,擁抱變化
2.外觀類對子系統的接口封裝,使得系統更加易于使用
缺點:
1.外觀類的接口膨脹,增加了使用成本
2.外觀類沒有遵循開閉原則,當子系統業務發生變化時,就要去修改外觀類。