定义
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
为了方便理解,我们可以看看下图,左边是未使用外观模式时,外部客户端直接调用企业中的各个子系统,调用链复杂且混乱,增大了客户端的使用难度,右边使用外观模式后,客户端直接跟外观系统交互,而不必再依赖内部子系统了,从客户端角度来看,调用变得简单了;而从企业系统内部来看,维护也变得容易了。
实际上,外观模式跟代理模式类似,也更偏向于架构模式,常见于企业应用集成中,企业应用集成包括界面集成,业务流程集成(过程集成),控制集成(应用集成,API集成),数据集成四个层面,而外观模式与业务流程集成(过程集成)密切相关,因为外观模式有业务流程优化的意味在里面,因此,外观模式有时也叫过程模式,例如淘宝网站首页就可以看成是一个外观模式的应用,因为它是多个系统的集成,并对外提供了一个一致的界面(不要死板的理解为API接口)。
UML类图
我们再来看一下外观模式的类图,其实,在该模式中,与其说是类图,不如说是架构图,因为从定义上也可以看出,外观模式面向的是各子系统,而非类与对象。因此,该模式也不必过于拘泥于代码实现,而应该更多的关注于它的设计思想,以及如何运用。
目的
- 为一个复杂的模块或子系统提供一个一致的外界访问接口,降低客户端访问子系统的复杂度。
- 使客户端与子系统之间解耦,让子系统内部模块更易维护和扩展。
- 进行访问控制,提高系统安全性。
- 维护大型遗留系统,小型系统没必要用外观,用代理就可以了。
和代理模式之间的异同
相同点
- 都可以在不改变子系统代码的基础上,对子系统加以控制;
- 原有系统之间都是可以直接访问的,两个模式都是为了让子系统更加容易使用;
- 都不应该在其中添加子系统没有的功能。
不同点
- 外观模式面向的是多个不同的子系统,而代理模式通常面向的是一个(或者多个相同的)子系统,例如,一个代理不能即负责代购又负责租房,但是外观却可以一条龙服务。
- 外观模式更多强调是对多个子系统的整合,而代理模式更多强调的是对某个子系统的代理,如果没有业务整合,外观也仅仅是个代理而已。
极端情况下,假如外观模式中的子系统只有一个,就跟代理模式差不多了,这有点像抽象工厂模式和工厂方法模式之间的关系。
思考
首先, DDD中的Service层是外观模式,因为它封装了下层的Repository,让上层更容易使用,同时上层也可以直接访问Repository层。那么,MVC中的Controller层,三层架构中的BLL层,微服务中的网关是不是外观模式呢?
- Controller不算外观模式,因为Controller虽然封装了Service层,但Service层本身不能被用户(Controller的上层)直接访问,因此不是外观,反而更像适配器;
- BLL层也不算外观模式,虽然从代码上看,他跟DDD中的Service层非常相似,甚至完全一样,但三层架构是横向切分,而DDD是纵向切分,他们从设计思想上有本质的区别。在三层架构中,虽然上层也可以直接访问到DAL层,但这种操作在设计上是不被允许的;
- 网关中用到了外观模式,网关比较复杂,其中大量用到了外观模式,但不等于外观模式,因为有时候网关也仅仅是个代理,并未做业务整合。
当然,在具体开发过程中,没必要过分拘泥于这些细节,因为满不满足外观模式的定义相对于好的设计而言,是即非充分也非必要条件,但是多思考一些细节却可以让自己想的更通透,何乐而不为呢?