C# 中的外观设计模式及其示例

2025年3月17日 | 阅读 7 分钟

C# 中的外观设计模式是什么?

根据 GOF 的定义,外观设计模式规定您必须为子系统中的一组接口提供一个单一的接口。外观设计模式定义的较高层接口使得子系统更容易使用。

一种称为外观设计的结构性设计,为复杂的类、库或框架系统提供了一个精简的用户界面。外观模式的主要目标是向外部客户展示一个最小、明确的接口,同时将所有复杂的底层任务分配给系统内的相关类。外观类通常是一个包装器,它覆盖了一组子系统,从而实现了它们之间的内聚通信。

正如名称所示,外观是指建筑物的正面。假设您只建造了一座建筑。走在外面的人能看到的建筑的唯一部分是玻璃和墙壁。建筑的内部设计、管道、电力和其他复杂的细节尚未被人们发现。换句话说,外观向在建筑物周围行走的人们展示了一个受欢迎的正面,同时隐藏了其所有复杂的细节。

通过一个真实的示例识别 C# 中的外观设计模式

确定复杂的子系统:首先确定您系统的哪些复杂组件需要简化。这些可能是拥有多个相互依赖类的复杂系统或库。

创建外观类:构建一个外观类,它为复杂的子系统提供了一个简单的接口。

将调用分配给子系统:外观应将客户端的请求分配给相关的子系统对象。外观应管理所有子系统的复杂性和依赖性。

客户端代码交互:通过使用外观与系统通信,客户端可以更轻松地使用复杂的子系统。

让我们通过一个真实示例来更好地理解 C# 中的外观设计模式。

为了帮助您理解,请查看随附的图表。在这种情况下,我们必须使用电子商务平台创建一个在线订购应用程序。

Facade Design Pattern in C# with Examples

如上图所示,客户端必须首先创建 Product 类的对象并调用 GetProductDetails 函数来获取产品详细信息,以便下订单。

然后,如果一切正常(即产品有货),您必须完成付款。客户端必须调用 MakePayment 函数并创建 Payment 类的实例才能完成此操作。如果付款成功,客户端必须创建 invoice 类的实例并使用 SendInvoice 函数将发票发送给客户。因此,客户端必须按特定顺序完成上述步骤才能下订单。

在 C# 中,外观设计模式包含一个额外的类,该类位于其他类的顶部。它有时被称为包装器类或外观类。

Facade Design Pattern in C# with Examples

因此,在本例中,额外的类 Order 只是外观类下订单的职责。这个类按特定顺序运行方法,并在内部创建每个类的实例。为了下订单,客户端现在将调用 Order 类、PlaceOrder 方法,而不是相应的类及其方法。PlaceOrder 函数将在内部使用 Product、Payment 和 Invoice 类来下订单。

注意:重要的是要记住,外观设计模式有助于将不期望的依赖项迁移到一处,同时还降低了程序的整体复杂性。

理解外观设计模式的类图或 UML 图

让我们仔细研究一下外观设计模式的各个元素和类图(也称为 UML 图)。为了理解外观设计模式的类图,请参考以下图形。

Facade Design Pattern in C# with Examples

如上图所示,外观设计模式涉及三个类。它们按以下顺序排列:

  • 外观类在确定哪个子系统类负责特定请求后,将客户端请求转发给相关的子系统对象。
  • 子系统类执行已委派给它们的相应功能;它们不知道外观类。

注意:尽管我们没有意识到,但在我们的项目中我们无意中广泛应用了外观设计模式。如果您正在处理 Web API,那么您就在使用外观设计模式。对于真实应用程序而言,这是最好的设计模式之一。理解外观设计模式将有助于您创建更好的项目架构。

在 C# 中实现外观设计模式

让我们一步一步地使用 C# 实现我们讨论过的示例。

步骤 1:创建子系统

Product、Payment 和 Invoice 类是示例中的子系统类;每个类都将负责其任务。因此,让我们建立上述三个类并分配职责。

付款子系统:确认产品有货后,您必须完成付款。在此过程中将使用付款子系统。因此,将以下代码复制并粘贴到名为 Payment.cs 的类文件中。此类中有一种付款方式。在此,您必须验证客户的付款方式。通过网上银行、UPI 或货到付款,您必须进行相应的付款。

发票子系统:付款成功后,我们必须向客户提供付款发票。因此,将以下代码复制并粘贴到名为 Invoice.cs 的类文件中。要发送发票,请使用此类的 Sendinvoice 函数。我们有时也会向客户发送付款失败发票。以下发票类可以接受来自外观类或直接来自客户端的请求。

注意:除了打印详细信息外,我们在此案例中尚未真正实现这些方法。我们的目标是理解 C# 中外观设计模式的实现,而不是专注于实际的方法实现。

步骤 2:创建外观类

它的功能类似于包装器类。因此,将以下代码复制并粘贴到名为 Order.cs 的类文件中。此类中的一个方法将创建子类的对象并按特定顺序调用相应的方法来下订单。客户端可以使用以下类提供的简单接口下订单。

借助外观类,我们现在隐藏了创建各种子类实例并调用其相应方法的复杂性。因此,此类充当了子类的包装器。PlaceOrder 方法完全负责下订单。

步骤 3:客户端

客户端是唯一将使用外观类的类。在我们的示例中,它将是 Programme 类的 Main 方法。因此,请对 Programme 类的 Main 方法进行以下修改。

外观设计模式的优点

  • 简化的接口:为复杂的子系统提供了一个单一、用户友好的接口,从而简化了它们的使用。
  • 隔离:隔离提供了与复杂子系统的一定程度的隔离,这在子系统经常发生变化的情况下非常有用。
  • 更好的可测试性和可维护性:通过关注系统接口并减少相互依赖性,外观可以简化测试过程。

实时应用

以下情况适用外观设计模式:

  • 简化复杂系统:您应该为由多个相互关联的类或层组成的复杂系统或框架提供一个简单的接口。外观设计可以隐藏这种复杂性,将其置于一个统一、简单的接口之下。
  • 解耦系统:通过隐藏客户端的底层复杂性,外观可以在组件紧密耦合或相互依赖的系统中提供松散耦合。
  • 分层架构:多层架构可以有一个外观,充当每个层级的入口。
  • 提高可读性和可用性:当您的目标是提高系统的可读性和可用性时。当一个复杂子系统具有清晰简单的接口(如外观)时,其他开发人员更容易理解和使用它。
  • 减少依赖:这种方法减少了外部代码对库或框架内部操作的依赖,使客户端代码免受未来更改或子系统复杂性的影响。
  • 标准化子系统接口:协调子系统接口。如果每个子系统都有不同的接口,外观可以提供一个一致的接口,从而更容易使用它们。

实现外观模式可以提高程序的封装性、可维护性和灵活性。它鼓励松散耦合,从而更容易在不影响客户端的情况下扩展或更改子系统。总而言之,外观模式是控制复杂性和增强 C# 等面向对象编程语言总体架构的有用工具。

结论

总之,通过提供一个单一的接口,C# 中的外观设计模式为简化与复杂子系统的通信提供了一种实用的方法。客户端可以通过一组定义清晰的方法与子系统通信,而无需了解其内部工作原理,因为子系统的复杂性被封装在一个单一的外观类后面。


下一个主题C# 中的不可变性