流畅的界面和生成器模式之间有什么区别?

2022-08-31 20:00:44

我对设计模式非常陌生,并且在流畅界面和构建器模式之间的区别方面遇到了麻烦。

我理解流畅界面的概念。但是生成器模式有点令人困惑。我无法理解在生成器模式中使用控制器。

我可以同时使用生成器模式和 Fluent 界面吗?如果是这样,那么我应该如何与董事和混凝土建筑商一起这样做?

我的问题不是关于构建器模式的优势。但这个问题的目的是了解构建器模式和流畅界面之间的关系。


使用 UML 序列图从 GoF 为生成器编辑:

Sequence diagram with director


答案 1

Fluent Interface 是语义表象。您可以将它们放在现有代码之上,以减少语法噪声,并在无处不在的语言中更清楚地表达代码的作用。这是构建内部域特定语言时使用的模式。这是关于可读性的。

导演/建造者协调某物的建造。也就是说,如果您正在构建披萨烘焙机,则控制器将确保从订单到披萨的步骤由正确的构建者以正确的顺序执行,并提供正确的数据。这是关于验证和委派的。

您当然可以将 Fluent 界面放在 Director/Builder 模式之上,使其阅读更多 - 流利 - 并强调域概念(与构建和委派的技术过程相比)。那可能是一个表达式生成器

我想强调的是,Fluent Interface不仅仅是方法链。这是一个常见的误解。方法链接是实现 Fluent 接口的一种方法,但它是不一样的,因为它缺乏语义质量,例如,这不是 Fluent 接口:

SomeObject.setFoo(1).setBar(2).setBaz(3);

以上并不表示有关某些对象的任何信息。它不是某种语义模型之上的门面。这只是一些链接的方法。Fluent Interface 的一个例子是 SQL 查询构建器,例如

SQLBuilder.select('foo').from('bar').where('foo = ?', 42).prepare();

在该 API 的底层是用于创建 SQL 语句的代码。它可能包含多个对象,显示的调用可以很好地创建一个 Select 对象,在其上调用一个 setter,创建一个 Condition 对象并将其应用于 Select 对象,最后返回一个 Statement 对象。但这一切都是隐藏的。这也凸显了 Fluent Interfaces 的另一个方面:它们可能违反了 SOLIDDemeter 定律。但是,由于它是代码之上的一个门面,希望遵循这些设计原则,因此这并不重要,因为您将违规行为本地化为 Fluent Interface。


答案 2

Fluent 接口背后的想法是,可以通过用点连接多个属性来将多个属性应用于对象,而不必每次都重新指定对象。构建器模式背后的想法是,未共享的可变对象通常比未共享的不可变对象更容易使用,但是对共享的不可变对象进行推理比共享的可变对象容易得多。因此,代码可以使用易于使用的可变对象来生成所需实例的“模型”,然后使用它来创建保存相同数据的易于共享的不可变对象。

这两个想法可以很好地协同工作,但有些正交。

请注意,流畅的界面至少有三种工作方式:

  • 通过让实例的每个成员返回一个应用了相应更改的新实例。
  • 通过让每个成员改变调用它的实例并返回该实例。
  • 通过让每个成员返回一个轻量级补丁对象的实例,该对象包含指向正在修改的内容或上一个补丁的链接。

最后一种样式要求采取一些操作来应用所有修补程序,但是如果被修改的对象很大并且需要进行许多更改,则可以最大程度地减少所需的复制量。