使用外观模式和MVC的优势是什么?

3

了解过外观模式,但不太明白使用的优势,主要是在MVC中使用。有人能帮我理解一下吗?可以给一些更实际的例子吗? 请原谅我的无知!


谷歌“facade设计模式示例”并开始阅读。 - DavidPostill
就像我之前所说的,我读了几篇文章并看了一些例子,但是并没有理解使用外观的有效性!换句话说,我没有意识到需要使用外观。 - Fabiano Moura
我认为MVC与问题完全无关... - Mike B
你要求更多实际的例子。在上面的谷歌搜索中返回了大量实际的例子。 - DavidPostill
DavidPostill,我理解您的意思,但正如我所提到的,我想了解使用Facade的重要性,特别是在MVC中。在我看到的所有示例中,这一点并不清楚。谢谢! - Fabiano Moura
3个回答

6

Facade Pattern 是一个聚合服务,提供多个上下文特性或服务。

来自维基百科

外观模式(或者门面模式)是一种常见的面向对象编程软件设计模式。该名称类比于建筑物的外立面。

一个外观是一个对象,它为一个更大的代码体提供了一个简化的接口,例如一个类库。 一个外观可以:

  • 使软件库更易于使用、理解和测试,因为外观有方便的方法用于常见任务;

  • 使库更易读,出于同样的原因;

  • 减少外部代码对库内部工作原理的依赖,因为大多数代码使用外观,从而允许在开发系统时更具灵活性;

  • 根据任务需求,使用单个良好设计的API封装糟糕设计的API集合。

话虽如此,简单说来,假设你有一个会计系统,其主表单为MDI,因此您有多个菜单,使用户可以访问这些功能。

为了避免多个依赖项,而不是编写类似以下内容的东西:

public class MainWindow : Form {
    public MainWindow(CustomerManagementPresenterFactory customerMgmt
        , SupplierManagementPresenterFactory supplierMgmt
        , InventoryManagementPresenterFactory inventoryMgmt
        , EmployeeManagementPresenterFactory employeeMgmt
        , StatementOfAccountManagementPresenterFactory statementOfAccntMgmt
        , InvoicesPastDueManagementPresenterFactory pastDueInvoicesMgmt) {
        // Work your dependencies here...
    }
}

当你清楚地看到你的MainWindow依赖于多个工厂(或其他),那么就是重构的时候了。一个问题是:
  • 我的MainWindow构造函数传递了太多依赖项吗?
答案是肯定的,我确实需要所有这些依赖项才能满足它的要求。
  • 如何重构以减少依赖项的数量?
有人可能会认为“过期发票”,“账户报表”和“客户管理”功能应该被聚合成一个服务。这就是Facade的作用。
public class CustomerManagement {
    public CustomerManagement(CustomerManagementPresenterFactory customerMgmt
        , StatementOfAccountManagementPresenterFactory statementOfAccntMgmt
        , InvoicesPastDueManagementPresenterFactory pastDueInvoicesMgmt) {
        // Work your dependencies here...
    }
}

现在MainWindow构造函数可以如下所示。

public class MainWindow : Form {
    public MainWindow(CustomerManagement customerMgmt
        , SupplierManagementPresenterFactory supplierMgmt
        , InventoryManagementPresenterFactory inventoryMgmt
        , EmployeeManagementPresenterFactory employeeMgmt) {
        // Work your dependencies here...
    }
}

然后,根据您的业务领域,SupplierManagement 可能与您的 InventoryManagement 密切相关,因此可以采取另一种聚合方式,如下所示。

public class InventoryManagement {
    public InventoryManagement(InventoryManagementPresenterFactory inventoryMgmt
        , SupplierManagementPresenterFactory supplierMgmt) {
        // Work your dependencies here...
    }
}

这样你可以进一步重构为:

public class MainWindow : Form {
    public MainWindow(CustomerManagement customerMgmt
        , InventoryManagement inventoryMgmt
        , EmployeeManagementPresenterFactory employeeMgmt) {
        // Work your dependencies here...
    }
}

现在,正如您所看到的,更容易理解 MainWindow 为实现其目的而做的事情。其背后的想法是将对您的业务领域有意义的内容进行分组。在另一个上下文中,人们可能更喜欢将CustomerManagementSupplierManagementEmployeeManagement分组在一起,因为它们具有类似的信息,例如NameAddressPhone NumberEmail等。这主要取决于您的需求。最终,外观的作用仍然相同,将类似的业务特性分组以添加抽象层并减少复杂性。

Mark Seemann 的一篇非常有趣的文章Refactoring to Aggregate Services 对此进行了详细讨论。

如果您想了解更多关于设计模式依赖注入的信息,我建议阅读Seemann先生的书:Dependency Injection in .NET">《.NET依赖注入》。尽管标题中包含.NET,但任何想学习依赖注入设计模式的人都应该阅读它以增进对这些主题的理解并提高技能水平。即使您不熟悉.NET,这些示例也很容易理解。

关于外观模式的其他有趣问答

免责声明

我知道你的问题标记为Java,但我发布了C#代码。这是为了快速回答而随口提及的。我认为,尽管我的示例是C#,但你可能很容易理解所展示的Facade示例的关键点,因为它们很简单。

1
感谢您的解释和示例。现在我清楚了如何以及在哪里使用外观模式! - Fabiano Moura
这是我看过的最好的解释了,而且我已经阅读了好几个小时。如果你有博客,请告诉我,我会关注的。 - Jabberwocky

1

外观模式旨在包装复杂功能,其主要目标是隐藏基础系统的复杂性。您可以将Facade想象为将复杂功能包装在一层中,并提供更简单的方法进行交互。

它为客户端提供接口,客户端可以使用该接口来访问系统。这种设计模式属于结构模式,因为该模式向现有系统添加了接口以隐藏其复杂性。

enter image description here


据我所知,门面只是用来调用更简单的方法,是吗?如果门面还涉及到一些业务规则,或者它在另一个层次上呢? - Fabiano Moura

0

MVC更像是计算机设计思维的一般方式。 MVC可以用于Web开发或桌面应用程序的对话中。 但是使用EJB或外观时,它确实变得更加具体和特定。 “它曾经处理所有事务管理器和持久性管理器的交互。” 您将使用类似于JSF作为视图和JPA或Hibernate的内容来做这件事。 此外,使用EJB提供了更多预制代码选项。

有时我认为某些主题之间的差异,例如外观和MVC,并不总是非常明显。


Rika对我来说一开始非常困惑。Will Marcouiller和Tushar Gupta提供的示例对于理解何时以及如何使用facade至关重要。特别是Will引用Marcouiller的那个例子!太棒了,易于理解! - Fabiano Moura

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接