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

Sag*_*gar 46 java oop design-patterns

我很擅长设计模式,并且在流畅的界面和Builder模式之间存在差异.

我理解流畅的接口的概念.但是构建器模式有点令人困惑.我无法理解在Builder模式中使用Director.

我可以一起使用Builder模式和Fluent Interface吗?如果是这样,那么我应该如何与导演和具体建筑师一起这样做?

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


使用GoF的Builder的UML序列图进行编辑:

与导演的序列图

Gor*_*don 131

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

导演/建筑师精心策划某物的建造.也就是说,如果您正在构建一台披萨烘焙机,则Director会确保从正确的顺序执行从订单到披萨的步骤,并使用正确的构建器执行正确的数据.这是关于验证和授权.

你当然可以在一个Director/Builder模式之上放置一个Fluent接口,使它更好 - 更好地阅读,并强调域概念(与构建和委派的技术过程相比).那可能是表达式构建器.

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

SomeObject.setFoo(1).setBar(2).setBaz(3);
Run Code Online (Sandbox Code Playgroud)

以上内容并未表达SomeObject的任何内容.它不是一些基于语义模型的外观.这只是一些链接的方法.Fluent Interface的一个例子是SQL查询构建器,例如

SQLBuilder.select('foo').from('bar').where('foo = ?', 42).prepare();
Run Code Online (Sandbox Code Playgroud)

在API的底层是创建SQL语句的代码.它可能包含多个对象,显示的调用可以很好地创建一个Select对象,在其上调用一个setter,创建一个Condition对象并将其应用于Select对象,最后返回一个Statement对象.但是这一切对我们来说是隐藏的.这也突出了Fluent Interfaces的另一个方面:它们可能违反了SOLIDDemeter法则.但是因为它是代码顶部的一个外观,希望遵循这些设计原则,所以并不重要,因为您将违规本地化到Fluent界面.

  • @Gordon因此,在我看来,语义不是界面Fluent的原因,因为您可以使用语句和分号轻松地使用与传统OOP样式界面相同的语义.Dave Fancher说:"流畅的界面是一种专门的,自我引用的方法链接形式,通过链条维护上下文." (7认同)
  • @supercat你的SQLBuilder将从任何调用返回*本身*的实例,所以你的foo和你的栏都引用了构建器.只有在调用prepare时才能完成构建过程并获得准备好的语句对象. (2认同)
  • 我发现你的SQLBuilder和SomeObject之间没有区别.每个都是简单的方法链接.我的观点是,流畅的接口只是方法链的一种模式.最酷的是当它们被构建为利用IDE时,通过返回仅支持从该点允许的操作的对象.你还说方法链是一种方法,但我认为这是错误的,没有方法链接的流畅界面根本不流利. (2认同)
  • @Gordon技术上他创造了这个词,所以我猜他是参考.然而,我仍然认为他过度销售他的大部分东西.Fluent是有效的方法链接精炼.我说的是关于smalltalk说话的链接,你在另一个方法上调用一个方法,所以你可以跳过一个局部变量.现在,如果你使用这个功能来构建一个聪明的DSL,你会很流利.问题是,"聪明"是有争议的.你的两个例子都很流利,一个更聪明,因此感觉更流畅.但如果不流利的话,第一个是什么? (2认同)

sup*_*cat 41

一个良好接口背后的想法是,人们可以通过将它们与连接点应用的多个属性的一个对象,而不必每次重新指定对象.构建器模式背后的想法是,非共享可变对象通常比非共享可变对象更容易使用,但是比共享可变对象更容易推理共享不可变对象.因此,代码可以使用易于使用的可变对象来生成所需实例的"模型",然后使用它来生成容纳相同数据的易于共享的不可变对象.

这两个想法可以很好地协同工作,但有点正交.请注意,流体接口至少有三种方式可以工作:让一个实例的每个成员返回一个应用了适当更改的新实例,让每个成员改变调用它的实例并返回它,或者通过每个成员返回一个轻量级补丁对象的实例,该对象包含要修改的事物或先前补丁的链接.最后一种样式要求采取一些操作来应用所有补丁,但如果要修改的对象很大并且需要进行许多更改,则可以最小化所需的复制量.

  • 不确定我是否同意您对Fluent Interface的定义.这听起来像只是方法链接.我不会投票,但请看我的答案,以解释Fluent Interfaces的实现. (6认同)
  • 不知道为什么人们批评你的答案,你很有见识.Fluent是一种模式,用于将方法级联添加到没有它的语言,并将级联与链接相结合.我也没有看到对构建器的批评,可变性/不变性是它的主要用例之一.虽然它可以用于更多的事情,比如在方法之间聚合参数,并进行验证等. (5认同)