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.外观类没有遵循开闭原则,当子系统业务发生变化时,就要去修改外观类。