介绍
外观模式 (Facade) 在开发中的运用频率非常高,尤其是在现阶段各种第三方 SDK 充斥在我们周边,而这些 SDK 很大概率会使用外观模式。通过一个外观类是的整个系统的接口只要一个统一的高层接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节。当然,我们在开发过程中,外观模式也是我们封装 API 的常用手段,例如网络模块,ImageLoader 模块等。
定义
要求一个子系统的外部与内部的通信必须通过一个统一的对象进行。门面模式 (Facade 模式)提供一个高层次的接口,使得子系统更易于使用。
使用场景
为一个复杂子系统提供一个简单接口,子系统往往因为不断演化而变得越来越复杂,甚至可能被替换。大多数模式使用时都会产生更多、更小的类,在使子系统更具可重用性的同时也更容易对子系统进行定制、修改,这种易变性是的隐藏子系统的具体实现变得尤为重要。Facade 可以提供一个简单统一的接口,对外隐藏子系统的具体实现,隔离变化
但你需要构建一个层次结构的子系统时,使用 Facade 模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,你可以让他们仅通过 Facade 接口进行通信,从而简化了他们之间的依赖关系
角色介绍
- Facade 系统对外的统一接口,系统内部系统地工作
- SystemA、SystemB... 子系统接口
外观模式接口比较简单,就是通过一个统一的接口对外提供服务,使得外部程序只通过一个类就可以实现系统内部的多种功能,而这些实现功能的内部子系统之间可能也有交互,或者说完成一个功能需要几个子系统之间进行写作,如果没有封装,那么用户就需要操作几个子系统的交互逻辑,容易出现错误,而通过外观类来对外屏蔽这些复杂的交互,降低用户使用成本。
Android 源码中的外观模式
ContextImpl 内部封装了很多不同子系统的操作,例如,Activity 的调转、发送广播、启动服务、设置壁纸等,这项工作并不在 ContextImpl 中实现,二十转交给具体的子系统进行处理。通过 Context 这个抽象定义了一组接口,ContextImpl 实现 Context 定义的接口,这使得用户可以通过 Context 这个接口统一进行 Android 系统的交互。用户与系统服务的交互都通过 Context 的高层接口,这样对用户屏蔽具体实现细节,降低使用成本。
总结
外观模式精髓在于“封装”二字,通过一个高层次结构为用户提供统一的 API 入口。使得用户通过一个类型就基本能够操作整个系统。减少用户是用户使用成本,提升系统灵活性
优点
- 对客户端因此子系统细节,减少客户端对于子系统的耦合,能够拥抱变化
- 外观类对于子系统的接口封装,使得系统更易使用
缺点
- 外观类接口膨胀,由于子系统的接口都有外观了统一对外暴露,使得外观类 API 接口较多,一定程度增加用户使用成本
- 外观类没有遵循开闭原则,当业务出现变化,可能需要直接修改外观类