翻译自大师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)。
分享到:
相关推荐
此文件为EDEM与ANSYS FLUENT耦合接口文件,其中分别有ANSYS18.0与EDEM2018.2;ANSYS18.1与EDEM2018.2;ANSYS18.2与EDEM2018.2;ANSYS19.0与EDEM2018.2;ANSYS19.2与EDEM2018.2。解压后可用记事本打开README.LINUX,依照...
《EDEM-Fluent耦合接口2.2版本编译与应用》 EDEM-Fluent耦合接口是用于模拟离散相(DPM)和连续相(CFD)之间相互作用的一种高级工具,它结合了EDEM(离散元素法软件)和Fluent(流体动力学软件)的优点,为多相流动...
"耦合接口2.2版本编译工具"是指用于构建和配置EDEM与FLUENT之间通信桥梁的特定工具集。这个版本可能包含了针对EDEM 2.2和FLUENT特定版本优化的代码和配置脚本,确保两者能正确交互并进行有效的计算。编译工具通常...
本压缩包"2.2版本EDEM+FLUENT耦合接口编译工具.rar"提供的内容,主要是针对这两个软件的接口编译工具,使得用户能够更方便地进行二者的协同计算。 在EDEM和FLUENT的耦合过程中,接口是至关重要的部分。它允许EDEM...
现在,我们可以在不污染 IService 接口的情况下,使用扩展方法实现 Fluent Interface: ```csharp IService aService = new Service(); aService.UseCache(new AppfabricCache()).UseLogger(new ConsoleLogger()); ...
:在工程实际中常遇到的流动、传热和燃烧等问题中,大都为分布...WinSock 网络通信原理,开发了FLUENT/MATLAB 接口,建立了分布参数模型闭环控制快速原 型的仿真平台,并且通过算例仿真验证了该方法的可行性与实用性。
《Fluent 2020R1与EDEM 2020耦合接口详解》 在现代工程模拟中,流体动力学和颗粒动力学的耦合分析日益重要,尤其是在处理固体颗粒与流体相互作用的问题时。Fluent作为一款广泛使用的商业流体动力学软件,能够精确地...
FLUENT-EDEM耦合接口,适用版本为FLUENT18.1+EDEM2017,亲测可用 已编译好,可以直接用,使用方法:FLUENT打开user-defined > Functions > Manage… ,在library Name中输入耦合接口所在路径,点击load按钮加载udf...
摘要:在工程实际中常遇到的流动、传热和燃烧等问题中,大都为分布参数系统。针对该分布参数模型建模难的问题,结合 CFD 仿真软件 FLUENT 和系统仿真软件 M
2022版edem—fluent欧拉耦合接口
FLUENT-EDEM耦合接口,适用版本为FLUENT16+EDEM2.7,亲测可用 已编译好,可以直接用,使用方法:FLUENT打开user-defined > Functions > Manage… ,在library Name中输入耦合接口所在路径,点击load按钮加载udf宏 ...
在"FluentInterface-main"这个压缩包中,我们可以预期包含的是一个与Fluent Interface相关的Java项目。可能的内容有: 1. **源代码**:项目的Java源代码,展示了如何实现Fluent Interface。每个类可能会有多个方法...
这种文件包含了模拟的详细配置,包括颗粒属性、边界条件以及与Fluent的接口设置。通过这个文件,用户可以启动EDEM并开始执行与Fluent的耦合计算。 “lib_edem_coupling”可能是一个库文件,它包含了EDEM与Fluent...
"lib_edem_coupling" 可能是一个动态链接库,为FLUENT提供与EDEM通信的接口函数。而 "load_edem_coupling.jou" 很可能是Joule文件,这是FLUENT使用的作业文件,用于设置和运行耦合模拟。 在这个耦合模拟中,用户...
耦合Fluent和EDEM的关键在于开发一个有效的接口,使得Fluent能够读取和响应EDEM模拟的结果,同时EDEM也能根据Fluent的流场信息更新颗粒的运动状态。这个过程通常涉及以下步骤: 1. **数据交换**:设计数据结构和...
本文将详细讲解"EDEM-FLUENT所有版本耦合欧拉接口"的相关知识点,包括它们的功能、耦合方法以及应用范围。 EDEM(Eulerian Discrete Element Method)是一款专门用于模拟颗粒流动的软件,它基于离散元方法,能够...
《FLUENT与EDEM的2.5版耦合接口详解》 在现代工程计算领域,流体动力学(CFD)与离散元素方法(DEM)的耦合应用日益重要,尤其在处理多相流体与颗粒交互的复杂问题时。FLUENT作为业界知名的CFD软件,而EDEM则专门...
标题中的“EDEM_FLUENT_Coupling_VOF_Serial_1_01.zip”指的是一个包含EDEM(离散元素方法,Discrete Element Method)与FLUENT(一款流体动力学模拟软件)耦合的VOF(Volume of Fluid,体积流体)序列化接口的压缩...
《激光辐射加热在Fluent中的应用详解》 激光辐射加热技术是现代工程和科学研究中的一种重要手段,尤其在材料加工、热处理、生物医学等领域有着广泛的应用。在这些领域,利用计算机模拟工具如Fluent进行热力学分析是...