圣诞大减价开始了!

外观

意图

外观是一种结构设计模式,它为库、框架或任何其他复杂的类集提供了简化接口。

立面设计模式

问题

想象一下,您必须使您的代码与属于复杂库或框架的广泛对象集一起工作。通常,您需要初始化所有这些对象,跟踪依赖关系,以正确的顺序执行方法,等等。

因此,类的业务逻辑将与第三方类的实现细节紧密耦合,使其难以理解和维护。

解决方案

facade是一个类,它为包含大量移动部件的复杂子系统提供简单接口。与直接使用子系统相比,facade可能提供有限的功能。然而,它只包含客户真正关心的那些特性。

当您需要将应用程序与具有数十个功能的复杂库集成时,拥有facade非常方便,但您只需要其中的一小部分功能。

例如,一款将猫的搞笑短视频上传到社交媒体的应用程序可能会使用专业的视频转换库。然而,它真正需要的只是一个具有单一方法的类编码(文件名,格式).在创建这样一个类并将其与视频转换库连接之后,您将拥有第一个facade。

真实的模拟

一个接听电话订单的例子

电话下单。

当您打电话给商店下电话订单时,接线员就是您对商店所有服务和部门的门面。运营商为您提供了一个简单的语音接口,可以连接到订购系统、支付网关和各种配送服务。

结构

立面设计模式的结构 立面设计模式的结构
  1. 外观提供对子系统功能的特定部分的方便访问。它知道在哪里指导客户的请求,以及如何操作所有的活动部件。

  2. 一个额外的外观类可以创建,以防止用不相关的特性污染单个外观,从而使其成为另一个复杂的结构。客户端和其他外观都可以使用其他外观。

  3. 复杂的子系统由几十个不同的对象组成。为了使它们都做一些有意义的事情,您必须深入研究子系统的实现细节,例如以正确的顺序初始化对象并以适当的格式为它们提供数据。

    子系统类不知道facade的存在。他们在系统内运作,并直接相互合作。

  4. 客户端使用facade而不是直接调用子系统对象。

伪代码

在本例中,外观Pattern使用复杂的视频转换框架简化了交互。

Facade模式示例的结构

在单个facade类中隔离多个依赖项的示例。

与其让代码直接与数十个框架类一起工作,不如创建一个facade类,它封装了该功能,并将其隐藏在其余代码中。这种结构还可以帮助您最大限度地减少升级到框架的未来版本或用另一个版本替换它的工作量。在应用程序中唯一需要更改的是facade方法的实现。

//这些是一个复杂的第三方视频转换框架的一些类。我们无法控制代码,因此//无法简化它。class VideoFile //…类OggCompressionCodec //…类MPEG4CompressionCodec //…class CodecFactory //…class BitrateReader //…AudioMixer //…//我们创建一个facade类来将框架的复杂性隐藏在一个简单的接口后面。这是功能性和简单性之间的权衡。 class VideoConverter is method convert(filename, format):File is file = new VideoFile(filename) sourceCodec = (new CodecFactory).extract(file) if (format == "mp4") destinationCodec = new MPEG4CompressionCodec() else destinationCodec = new OggCompressionCodec() buffer = BitrateReader.read(filename, sourceCodec) result = BitrateReader.convert(buffer, destinationCodec) result = (new AudioMixer()).fix(result) return new File(result) // Application classes don't depend on a billion classes // provided by the complex framework. Also, if you decide to // switch frameworks, you only need to rewrite the facade class. class Application is method main() is convertor = new VideoConverter() mp4 = convertor.convert("funny-cats-video.ogg", "mp4") mp4.save()

适用性

当您需要对复杂的子系统有一个有限但直接的接口时,请使用Facade模式。

通常,子系统会随着时间的推移而变得更加复杂。即使应用设计模式通常也会导致188bet平台电子游戏创建更多的类。子系统可能变得更灵活,更容易在各种上下文中重用,但是它需要从客户端获得的配置和样板代码的数量会越来越大。Facade试图通过提供一个快捷方式来解决这个问题,该快捷方式可以访问子系统中最常用的功能,满足大多数客户的需求。

当您想要将子系统结构成层时,请使用Facade。

创建外观以定义子系统的每个级别的入口点。您可以通过要求多个子系统仅通过外观通信来减少它们之间的耦合。

例如,让我们回到视频转换框架。它可以分为两层:视频相关和音频相关。对于每一层,您可以创建一个外观,然后使每一层的类通过这些外观相互通信。这种方法与中介模式。

如何实施

  1. 检查是否有可能提供比现有子系统已经提供的更简单的接口。如果这个接口使客户端代码独立于子系统的许多类,那么您就走上了正确的道路。

  2. 在一个新的facade类中声明并实现这个接口。facade应该将来自客户端代码的调用重定向到子系统的适当对象。facade应该负责初始化子系统并管理其进一步的生命周期,除非客户端代码已经这样做了。

  3. 为了充分利用该模式,让所有客户端代码仅通过facade与子系统通信。现在客户端代码不受子系统代码更改的影响。例如,当子系统升级到新版本时,您只需要修改facade中的代码。

  4. 如果立面变成太大,考虑将其部分行为提取到一个新的、精炼的facade类中。

利与弊

  • 您可以将代码与子系统的复杂性隔离开来。

与其他模式的关系

  • 外观为现有对象定义一个新接口,而适配器试图使现有的界面可用。适配器通常只包装一个对象,而外观使用对象的整个子系统。

  • 抽象工厂可以作为替代品吗外观当您只想从客户端代码中隐藏子系统对象的创建方式时。

  • 轻量级选手展示了如何制作许多小对象,然而外观演示如何生成表示整个子系统的单个对象。

  • 外观而且中介有类似的工作:他们试图组织许多紧密耦合的类之间的协作。

    • 外观定义对象子系统的简化接口,但没有引入任何新功能。子系统本身并不知道facade。子系统中的对象可以直接通信。
    • 中介集中系统组件之间的通信。组件只知道中介对象,不直接通信。
  • 一个外观类通常可以转换为类单例因为在大多数情况下,单个facade对象就足够了。

  • 外观类似于代理在这两者缓冲一个复杂的实体和初始化它自己。不像外观代理具有与其服务对象相同的接口,这使得它们可以互换。

代码示例

c#外观c++中的FacadeGo中的门面Java中的FacadePHP外观Python中的FacadeRuby的外观生锈的立面Swift的立面TypeScript中的Facade

Baidu
map