Design-Pattern-Facade
外观/门面模式(Facade)是一种结构型设计模式,能为程序库、框架或其他复杂类提供一个简单的接口。
场景
为了通用性,第三方库/子系统会把功能设计得完备,但客户端通常只使用其中非常少的功能。客户端直接使用第三方库类,会引入过多不必要的功能与方法细节,也会导致客户端会与第三方类的实现细节紧密耦合。当想尝试替换其他功能相似的第三方库时,客户端需要调整所有调用第三方库方法的位置。如果客户端需要同时与多个第三方库交互,类的创建,库之间的依赖,交互流程的顺序,对于客户端来说都是过于复杂的。
门面模式
简单来说,门面模式就是为了让客户端更方便地使用子系统。
门面模式为子系统中的一组接口提供一个统一的高层接口。它就像是一个门面,将子系统的复杂性封装起来,让外部调用者只需要与这个门面进行交互,而不需要了解子系统内部的具体实现细节。就像通过电话给商店下达订单时,接线员就是该商店的所有服务和部门的门面。接线员为你提供了一个同购物系统、支付网关和各种送货服务进行互动的简单语音接口。
门面模式的结构比较简单,包含两个角色,门面和子系统。其中子系统通常是第三方库,而门面则负责封装所需功能并隐藏其他代码,从而无需使全部代码直接与数十个第三方类进行交互。
1 |
|
门面模式变体
上例中,将门面设计成了类。如果要替换第三方库实现时,则需要修改门面类,一定程度上不符合开闭原则。
如果对门面再抽象一层,可以将门面设计成接口。在门面接口中定义客户端需要的方法,客户端也只与门面交互。如此一来,替换第三方库实现,可以通过新增门面接口的实现类来完成。
大名鼎鼎的SLF4J(Simple Logging Facade forJava)
就是门面模式的典型实现,其中的F
指的就是Facade
门面。java
中,可以完成日志功能的第三方库有许多,例如log4j
、logback
、java.util.logging
,不同的日志实现提供的接口也不同。当需要将项目中的日志实现从一个替换成另一个,或者日志实现发生了代码变动,所有引用的地方都需要进行改动。而SLF4J
则为这些不同的日志实现,统一规定了交互接口。客户端仅通过SLF4J
的接口,与各种不同的日志实现交互。当需要替换日志实现时,只需要替换SLF4J
门面的具体实现,这通常也被包含在第三方库中,因此客户端代码无需进行任何调整。
此外,如果门面接口包含的功能太多,不符合单一职责原则,可以通过将接口拆分成多个接口,并通过继承来组织接口之间的关系。
总结
门面模式的动机就是让客户端更简单地使用第三方库。类似把课本中关注的重点抄到笔记本上,后续不翻书本,只翻笔记了。
门面模式可以降低客户端与第三方库之间的耦合。使得替换第三方库时,可以最小程度改动客户端代码。
简单的门面可以设计成类,并在其中实现对子系统的创建与交互。复杂的门面可以设计成接口,并通过不同实现类,完成对不同子系统的交互,以符合开闭原则。SLF4J
就是典型例子。
门面被设计成接口时,可以通过接口拆分和继承,来组织接口的关系。