---转载自http://huidian.iteye.com/blog/426664
翻译自大师martin fowler 05年的博客文章,虽然时效性太差,不过许多开源项目中都用到了这种接口的设计风格,权当学习吧。
原文地址http://martinfowler.com/bliki/FluentInterface.html
几个月前,我同Eric Evans参加一个工作讨论组,Eric谈到某种接口风格,我们决定将它命名为Fluent Interface(连贯接口)。这不是个通用风格,但我们认为应该值得认识。可能认识它的最好方式是通过例子。
一个最简单的例子可能是Eric的timeAndMoney库。在一般情况下,为获得时间间隔段,我们可能会看到如下代码:
- TimePoint fiveOClock, sixOClock;
- ...
- TimeInterval meetingTime = new TimeInterval(fiveOClock, sixOClock);
timeAndMoney库的使用者可通过下面方式使用该库:
- TimeInterval meetingTime = fiveOClock.until(sixOClock);
我将继续一个更为通用的,顾客填写订单的例子。订单是一列列的关于数量与产品的条目,其中有一列可以跳过,这意味着,我宁愿这列不填写,也得让不能延误整个订单的投递。因此我需要给予整个订单一个rush状态。
我看到的大部分对该类情况的代码像下面这样:
- private void makeNormal(Customer customer) {
- Order o1 = new Order();
- customer.addOrder(o1);
- OrderLine line1 = new OrderLine(6, Product.find("TAL"));
- o1.addLine(line1);
- OrderLine line2 = new OrderLine(5, Product.find("HPK"));
- o1.addLine(line2);
- OrderLine line3 = new OrderLine(3, Product.find("LGV"));
- o1.addLine(line3);
- line2.setSkippable(true);
- o1.setRush(true);
- }
大体上是创建了不同的对象并把它们装配起来,如果不能通过构造函数的方式来添加,那么我们需要使用临时的变量来完成装载。(这里是利用了集合)
下面是利用Fluent(连贯)风格来设计接口的代码:
- private void makeFluent(Customer customer) {
- customer.newOrder()
- .with(6, "TAL")
- .with(5, "HPK").skippable()
- .with(3, "LGV")
- .priorityRush();
- }
可能值得重视的是,该风格类似一种内部"DomainSpecificLanguage(DSL领域特定语言)",这也是我们为何用"Fluent(连贯)"来描述它。很多情况下,这两者是同义词。API设计的最基本要求是可读性和流畅性,因此花费更多精力去思考API结构本身让它更加连贯是有价值的。简单的如一些构造器,setter以及单纯的添加方法是很容易写出,而提出一个优秀的Fluent(连贯)的API则需要一些思考。
正当我在Calgary一家咖啡厅匆忙的完成早餐时,确信这种风格存在一个问题(个人理解,或许是作者是想表达因为赶早餐而有感而发),好的Fluent(连贯)API需要花费一些时间来构建。如果你需要更多类似例子,可以参考http://www.jmock.org/(JMOCK),JMOCK和其他的MOCK库一样,需要创建复杂的行为规范。近些年已经构建了很多mocking库,而JMOCK包含了一些让程序十分流畅的,相当优美的Fluent(连贯)API。下面是一个例子:
- mock.expects(once()).method("m").with( or(stringContains("hello"),
- stringContains("howdy")) );
我注意到,Steve Freeman和Nat Price关于JMOCK的API演变有一次非常成功的对话(JAOO2005),交谈结果记录在OOPSLA paper。
至此,我们通常看到Fluent(连贯)API被用来构建对象配置,且是值对象。尽管我怀疑这是一种共识,但不能确定这是否就是该类接口的特质。就本人而言,是否连贯的关键,在于作为DSL的特质。使用API时,越感觉行云流水,那么它就越连贯。
构建一个Fluent(连贯)API可能会出现一些不寻常的习惯。最明显的是setter方法将会返回一个值。(在订单的例子中,with这个添加一行订单信息的方法将返回这个订单)在传统的观点中,修改状态的方法一般返回为void,可以查看以下原则Command Query Separation,这个观点与Fluent(连贯)API有所冲突,因此我倾向于在这种场景下,将先忽略这个习惯。
你需要选择一个返回值的类型,基于你设计如何让这个“动作连贯的流转下去”,JMOCK一个主要的观点是,返回类型依赖于你下一个动作需要什么类型。这种观点的好处在于,在IDE向导下,方法调用完成后,很容易知道下个调用类型。通常我发现,动态语言更适合于DSLs是因为它们的语法更加整洁。而使用这种Fluent(连贯)API,算是对静态语言的补充。
Fluent(连贯)API另外一个问题是,它无法很好的描述自身.察看方法名with,或许可以认为这个方法名不太合适,以至于无法很好的表达自身的意图.只是它仅仅在整个连贯动作的上下文语义中,所表达的意义才能被凸现.因此一个解决的途径,就是
Eric提及的他至今为止的使用情况, Fluent(连贯)接口大部分用于值对象配置。值对象没有领域特征,你能很容易的使用及传递它。因此可以在顺畅的流转过程中被重新赋值。
我没有看到大量的Fluent(连贯)API实例,因此我们无法对它的优缺点下结论。而现在还处于推广期,不管如何,我认为它已经准备就绪。
(08年6月更新)自从我写这篇blog来,它的使用范围越来越广泛了,这给予我很大的鼓舞。我《 fluent interfaces and internal DSLs 》中改进了我的观点。我也注意到一个普遍的错误观点——很多人认为Fluent(连贯)API等同于方法链(Method Chaining),确实链在Fluent(连贯)API中是一个应用得很普遍的技术,但是Fluent(连贯)API本身远远不只这些。
我看到JMock的例子中,不只用到方法链,还用到嵌套函数以及对象范围(object scoping)。
相关推荐
Fluent Interface 是一种设计模式,它使得代码更加可读且表达性强,特别是在 C# 中,通过使用扩展方法和方法链可以很容易地实现。在本文中,我们将探讨在 C# 中实现 Fluent Interface 的三种方法。 首先,让我们...
在"FluentInterface-main"这个压缩包中,我们可以预期包含的是一个与Fluent Interface相关的Java项目。可能的内容有: 1. **源代码**:项目的Java源代码,展示了如何实现Fluent Interface。每个类可能会有多个方法...
4. **Fluent Interface(Fluent接口)**:在Fluent中调用UDF的设置。 **三、UDF编写步骤** 1. **创建头文件**:首先定义UDF所需的函数、变量和数据结构。 2. **编写源文件**:实现UDF的具体功能,如计算新的源项、...
流利接口(Fluent Interface)是一种设计模式,它使得代码可读性更强,更像自然语言,从而提高代码的可维护性和理解性。在Java编程中,这种模式被广泛用于构建对象之间的交互,尤其是当涉及到复杂的配置或者构建过程...
- **Fluent Interface**:提供了一个友好的图形界面,用户可以在其中编写和测试UDFs。 - **Text Editor**:推荐使用具有语法高亮显示功能的文本编辑器来编写代码,以提高效率和可读性。 3. **编程语言**: - ...
This tutorial assumes that you are familiar with the FLUENT interface and have a good understanding of the basic setup and solution procedures. Some steps will not be shown explicitly. This tutorial ...
| |Trabalhando网站设计模式Fluent接口e Builder-Pré :rocket: 技术Esse projeto foi desenvolvido com是seguintes tecnologias: -1.22.4 -6.14.5 - v15.12.0 :laptop: 普罗耶托Projeto com Node.js支持UMTS和...
这是一篇教程文章,首先介绍了C#中的Fluent接口模式。接下来是对分层Fluent接口的讨论。最后,讨论了Fluent Interface Pattern中一个相当复杂的继承问题。目标受众是中级C#程序员及以上。
《激光辐射加热在Fluent中的应用详解》 激光辐射加热技术是现代工程和科学研究中的一种重要手段,尤其在材料加工、热处理、生物医学等领域有着广泛的应用。在这些领域,利用计算机模拟工具如Fluent进行热力学分析是...
- **Fluent Interface**:熟悉 Fluent 提供的 API,如 `UDF_Init()`, `UDF_Finalize()`, `U_GetField()`, `U_SetField()` 等,它们是 UDF 与 Fluent 交互的桥梁。 通过研究这个源码压缩包,开发者可以学习到如何...
FluentInterface query syntax RoR ActiveRecord style syntax Ambient transaction Dynamic object Partial update 1:1 1:Many Many:Many relations Auto create table Anti sql injection Multiple data ...
Fluent是一款广泛应用于流体力学、热力学以及多物理场模拟的软件,是ANSYS公司产品线中的一个重要组件。Gambit则是一个专门用于几何建模、网格划分的前处理器,而Exceed则可能是指一种远程桌面连接工具,用于在...
fluent19.2用户知道手册,884页以及一些相应算例的压缩包
在使用Fluent进行流体动力学模拟时,经常会遇到各种问题,尤其是对于初学者和进阶用户来说。本文将探讨一些常见的问题及其解决方案。 首先,关于"wall-shadow"的概念。"wall-shadow"并非用户手动定义,而是Fluent...
Fluent-validator 是一套 Java 的轻量验证框架,提供流式风格(Fluent Interface)的调用体验,类似 JDK8 stream式的 API,支持注解式验证器,支持 JSR303 -Bean Validation 标准最佳实现 Hibernate Validator 集成...
特点:使用纯java语法(Fluent Interface)制定用户的词法、语法规则;jdk1.6 compiler API动态编译为字节码;自动管理字节码、用户无需关心具体生成的解析器源码;专为DSL打造,相对与使用其它常见工具(javacc, ...
在ANSYS Fluent中进行空气射流的模拟是流体动力学分析中的一个重要应用,尤其当涉及到多相流问题时,复杂性进一步增加。本案例是一个典型的三相流动问题,涉及空气、水蒸气和液态水。下面我们将深入探讨相关的知识点...
FLUENT 2020R2 tutorial guide PDF及案例源文件 1.What’s In This Manual The ANSYS Fluent Tutorial Guide contains a number of tutorials that teach you how to use ANSYS Flu- ent to solve different types ...
开源Codeplex其主页简介:该组件是一个轻量级的.NET类库,使用流畅的接口定义和lambda表达式为构建一个业务类的验证规则(A small validation library for .NET that uses a fluent interface and lambda ...