《设计模式》— 结构型模式 — 外观模式
一、动机
将一个系统划分成若干个子系统有利于降低系统地复杂性。一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小。达到该目标的途径之一就是引入一个外观对象,它为子系统中较为一般的设施提供了一个单一而简单的界面。
这个模式在如 Windows 操作系统中应用的十分广泛。在使用命令行作为交互工具的操作系统中,其提供的各项功能固然强大,但是这种交互方式却不适合普通用户使用。在 Windows 操作系统中,提供了一个用户界面并且对用户屏蔽了底层 exe 的调用。对于普通用户,他们可以通过这样的 GUI 界面进行各种操作。对于少数懂得如何使用底层工具的人,他们仍旧可以通过 dos 和 命令行参数实现定制化和更强大的功能。
二、适用性
- 当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂,大多数模式使用时都会产生更多更小的类。这使得子系统更具可复用性,也更容易对子系统进行定制,但也给那些不需要定制子系统的用户带来一些使用上的困难。Facade 可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过 Facada 层。
- 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入 Facade 将这个子系统与客户及其他的子系统分离,可以提高子系统的独立性和可移植性。
- 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,可以让他们仅通过 Facade 进行通信,从而简化了它们之间的依赖关系。
三、结构
四、参与者
1、Facade
- 知道哪些子系统负责处理请求
- 将客户的请求代理给适当的子系统对象
2、子系统类
- 实现子系统的功能
- 处理由 Facade 对象指派的任务
- 没有 Facade 的任何相关信息
五、效果
1、对客户屏蔽子系统组件
这可以有效减少客户需要处理的对象的数目,并使得子系统使用起来更加方便。
2、实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。
松耦合关系使得子系统的组件变化不会影响到它的客户。Facade 模式有助于建立层次结构系统,也有助于对对象之间的依赖关系分层。Facade 模式可以消除复杂的循环依赖关系。这一点在客户系统与子系统分别实现的时候尤为重要。
在大型软件系统中降低编译依赖性至关重要。在子系统类改变时,希望尽量减少重编译工作以节省时间。用 Facade 可以降低编译依赖性,限制重要系统中较小的变化所需的重编译工作。Facade 模式同样也有利于简化系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。
3、子系统对客户开放
我们可以在系统易用性和通用性上自行权衡。
六、实现
1、降低客户 - 子系统之间的耦合度
用抽象类实现 Facade 而它的具体子类对应于不同的子系统实现,这可以进一步降低客户与子系统的耦合度。这样,客户就可以通过抽象的 Facade 类接口与子系统通信。这种抽象耦合关系使得客户不知道它使用的是子系统的哪个实现(可以和抽象工厂模式结合)。
除生成子类的方法以外,另一种方法使用不同的子系统对象配置 Facade 对象。为定制 Facade ,仅需对它的子系统对象进行替换。
2、公共子系统类与私有子系统类
一个子系统与一个类的相似之处是,它们都有接口并且都封装了一些东西 —— 类封装了状态和操作,而子系统封装了一些类。考虑一个类的公共和私有接口是有益的,我们也可以考虑子系统的公共和私有接口。
子系统的公共接口包含所有的客户程序可以访问的类。私有接口仅用于对子系统进行扩充。当然 Facade 类是公共接口的一部分,但它不是唯一的部分,子系统的其他部分通常也是公共的。例如,编译子系统中的 Parser 类和 Scanner 类就是公共接口的一部分。
私有化子系统类确实有用。在C++中,我们可以借由名称空间仅暴露公共子系统。