Facade模式的关键特征

意图

  • 希望简化原有系统的使用方式。需要定义自己的接口。

    为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口,使子系统更加容易使用。

问题

  • 只需要使用某个复杂系统的子集
  • 需要以一种特殊的方式与系统交互。

    通过这个模式我们能够更容易地使用一个复杂的系统,要么只使用系统的一部分功能,要么是以特殊方式使用系统。

f224391d4e5b23a7db06149fdbd89555.png

2c11f4489a2926a9827dd3afa1f217f6.png

解决方案
Facade为原有系统的客户提供了一个新的接口。
为客户提供的一个简化接口,使系统更容易使用。
涉及对象是参与者与协作者

效果
Facade模式简化了对所需子系统的使用过程。
但是,由于Facade并不完整,因此客户可能无法使用某些功能。

实现
定义一个(或多个)具备所需接口的新类。
让新的类使用原有的系统。

[!caution] 需要注意的地方
Facade模式只在使用系统的一部分功能,或者在以特殊方式与系统交互时才有效。
如果系统的所有功能都需要使用,那么除非最初的设计很糟,否则并无余地对设计进行改进。

Facade模式的变体:

减少客户必须处理的对象数量

Facade不仅可以用来通过方法调用创建更简单的接口,还能用来减少客户必须处理的对象数量。例如,假设有一个 Client 对象必须处理Database、Model、Element对象。Client必须首先通过 Database对象打开数据库,获取Model对象,然后再查询Model对象,获取Element对象,最后请求Element对象的信息。如果能够创建一个可供Client查询的Database Facade,那么以上过程将容易得多。

ca7e280a7c8c5d3a10a7770596b8acbb.png

[!NOTE] 让一个Facade为多个对象工作
如果Facade能够设计成无状态的(也就是说,其中没有存储状态),则一个Facade对象就能够被多个其他对象使用。

用新的例程补充原有功能

假设除了使用系统中原有功能之外,我还需要提供一些新功能——比如,记录对特定例程的所有调用。这种情况下,就不仅仅是使用系统的部分功能了。

这时,我为Facade类所写的方法中可以为新的功能增加一些新例程。这仍然是Facade模式,但是增加了新的功能。我认为其主要目的是简化,因为我不想强制客户例程知道它还需要调用额外的例程——让 Facade 去做好了。

Facade 模式提出了一种通用方法;它为我提供了起点。这个模式的Facade部分实际上就是创建了一个新的接口供客户使用,来代替系统的原有接口。我之所以能够这样做,是因为Client对象并不需要原系统提供的所有功能。

Facade模式的变体:一个“封装”层

Facade模式还可以用来隐藏或者封装系统。Facade类能够将系统作为自己的私有成员包含进来。在此情况下,原系统将与Facade类联系起来,但Facade类的客户无需看到。

封装系统的原因包括以下几种。

  • 跟踪系统的使用情况 ——通过强制所有对系统的访问都必须经过Facade,可以很容易地监视系统的使用情况。
  • 改换系统 ——未来可能需要切换系统。通过将原系统作为 Facade类的一个私有成员,可以最省力地将切换到新的系统。当然,可能还要做很多工作,但是至少我只需在一个地方修改代码(Facade类)就行了。

[!faq] 如果需要在系统所提供的功能之外添加功能,还能使用facade设计模式吗
外观模式的主要目的是为子系统提供一个一致的接口,简化复杂系统的使用。即使是在已有系统上添加新功能,外观模式仍然可以派上用场。

[!faq] 什么情况下应该编写一个新系统而不是使用facade封装老系统
现有系统无法满足核心需求:当现有系统的功能已经无法满足业务的核心需求,或需要彻底改变原有的业务流程和逻辑时,重新构建一个新系统可能是更好的选择。
现有系统过于复杂和混乱:重构或封装成本过高时,重新开发一个新系统可能更为经济有效。
性能问题:当现有系统的性能无法满足新需求或其性能瓶颈无法通过简单封装来解决时,重新开发一个专门为高性能需求设计的系统可能会更有效。
对现有系统的修改风险过高:如果对现有系统的任何修改都会引发较大的稳定性和安全性问题,封装在此场景下可能无助于真正解决问题,构建一个更安全、稳定的新系统是更合适的选择。
扩展性差:如果现有系统设计导致新功能的扩展非常困难,需要花费过多的时间和精力去修改和测试,那么构建一个新的系统并使其更具扩展性可能会更合理。

当现有系统的局限性和维护成本无法被外观模式所解决,或者长远来看会对业务造成阻碍时,开发一个新系统通常是更可行和有效的选择。

[!faq] 在facade中,客户是如何访问子系统的
在外观模式(Facade Pattern)中,客户端并不直接访问子系统的组件。相反,客户端通过外观类(Facade)与子系统交互,外观类对外提供一个统一、简化的接口来隐藏子系统的复杂性和细节。


<
Previous Post
来杯大麦茶 Adapter模式
>
Next Post
Apriori 算法讲解