只读接口模式和门面模式有什么区别?

What is the difference between the read-only interface pattern and the facade pattern?

假设我为 class 编写了一个外观并公开了它的所有方法,除了它的 setter。与只读界面模式的功能性区别是什么?

基于 wikipedia article on immutable interfaces 我会说外观具有不可变接口的优点(当我命名我的 class Foo 并且我的外观是 ImmutableFoo 时)而没有被能够转换不可变接口 "to their concrete, mutable type, and have their state mutated".

编辑

事实证明,维基百科上关于不可变接口的文章并没有讨论 slide 49 and 50 in this presentation 中描述的只读接口模式。答案是外观和只读接口确实可以通过使用包装器 class 来实现,但是它们有不同的用途(请参阅已接受的答案和评论以获得更详细的观察)。

Facade 模式的主要目的不是让你的界面不可变。

来自 Wikipedia:

A facade is an object that provides a simplified interface to a larger body of code, such as a class library. A facade can:

  • make a software library easier to use, understand and test, since the facade has convenient methods for common tasks;
  • make the library more readable, for the same reason;
  • reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system;
  • wrap a poorly designed collection of APIs with a single well-designed API (as per task needs).

外观可以是可变的。它们用于提供简化的界面。

在你调用一个class一个'Facade'之前,你应该问问自己,它是否提供了一个简化的界面并使库更易于使用?

它们可能有一些重叠,但主要目的不同。

外观就是API简化

假设您正在为电子商务系统开发订单处理功能。您的核心库提供三种方法:ChangeOrderStatus()SendOrderToFulfillment()SendOrderUpdateEmailToCustomer().

没有门面,您必须在需要批准订单的任何地方调用所有这三个方法。太无聊了,而且很容易出错。如果您将 ApproveOrder() 方法添加为 Facade(它只是调用这三个方法),您只需在需要批准订单的任何地方调用 ApproveOrder() .这简化了 api,并使库更易于使用。

如果您的应用程序明显分为多个层。您的基础架构层之上可能有一个非常薄的 Facade Layer。您的所有 UI 代码都将与外观层而不是基础结构层交互。在我的例子中,ApproveOrder()在外观层,而ChangeOrderStatus()SendOrderToFulfillment()SendOrderUpdateEmailToCustomer在基础设施层。

只读界面是关于数据保护

有些对象应该是不可变的。例如,immutable 对象在多线程中通常是首选,因为它们不公开改变其状态的方法,因此它们可以安全地在线程之间共享。

模式与目标

从您提到的slide(第50页)来看,“只读接口”模式是实现“不可变”的具体模式。但这并不是实现“不可变”的唯一方法。

如果您遵循特定的“只读接口”模式,我们可以说您实现了该模式。但是如果你使用其他一些方法来实现“不可变”,我们不能说你实现了“只读接口”模式,但你确实达到了“不可变”的目标。

是否实现“只读接口”模式重要吗?当然不是,你关心的是“不可变”,而不是具体的“只读接口”模式。 (有时候,api有setter,但是如果你调用它们会抛出异常。这是实现“不可变”的另一种方式。你只需要选择最合适的解决方案来实现相同的目标。)