Mar*_*rga 22 java design-patterns chaining
我最感兴趣的是Java,但我认为这是一个普遍的问题.最近我一直在使用Arquillian framework(ShrinkWrap),它使用了很多方法链接.方法链接的其他实例是在方法StringBuilder,StringBuffer.使用这种方法有明显的好处:减少详细程度就是其中之一.
现在我想知道,为什么并非所有将void返回参数实现为可链接的方法?链接必然存在一些明显和客观的缺点.因为如果所有方法都是可链接的,我仍然可以选择不使用它.
我不是要求改变Java中的现有代码,这可能会破坏某些地方的某些东西,但解释为什么不使用它也会很好.我更多地要求从未来的框架(用Java编写)设计视角.
我发现了一个类似的问题,但原来的提问者实际上想知道为什么它被认为是一种好的做法:方法链 - 为什么这是一个好的做法,或不是?
虽然有一些答案可用,但我仍然不确定链接的所有优点和缺点是什么,以及将所有void方法链接起来是否有用会被认为是有用的.
Ric*_*gle 24
缺点
优点
它允许将数学方程式样式代码写成完整的方程式,而不需要多个中间对象(导致不必要的开销),例如,如果没有方法链接,矢量三重交叉乘积(作为随机示例)将必须写为
MyVector3d tripleCrossProduct=(vector1.multiply(vector2)).multiply(vector3);
Run Code Online (Sandbox Code Playgroud)
它的缺点是创建一个必须创建和垃圾收集的中间对象,或者
MyVector3d tripleCrossProduct=vector1;
tripleCrossProduct.multiplyLocal(vec2);
tripleCrossProduct.multiplyLocal(vec3);
Run Code Online (Sandbox Code Playgroud)
这避免了中间对象的创建但是很不清楚,变量名tripleCrossProduct实际上是直到第3行的谎言.但是,如果你有方法链接,这可以用正常的数学方式简洁地编写,而不会创建不必要的中间对象.
MyVector3d tripleCrossProduct=vector1.multiplyLocal(vector2).multiplyLocal(vector3);
Run Code Online (Sandbox Code Playgroud)
所有这一切都假设vector1是牺牲性的,永远不需要再次使用
当然还有明显的好处; 简洁.即使您的操作没有链接到我上面示例的庄园中,您仍然可以避免对该对象的不必要的引用
SomeObject someObject=new SomeObject();
someObject
.someOperation()
.someOtherOperation();
Run Code Online (Sandbox Code Playgroud)NB MyVector3d不是用作真正的Java类,而是假设.multiply()在调用方法时执行交叉产品..cross()没有使用,以便那些不熟悉矢量微积分的人的'意图'更清楚
NB Amit的解决方案是使用多线方法链的第一个答案,我把它作为完整性的第四个要点的一部分包括在内
Ten*_*giz 19
方法链接是一种实现流畅接口的方法,无论编程语言如何.它的主要好处(可读代码)告诉您何时使用它.如果对可读代码没有特别需要,最好避免使用它,除非API自然地设计为由于方法调用而返回上下文/对象.
必须针对命令查询API考虑Fluent接口.为了更好地理解它,让我在下面编写命令查询API的子弹列表定义.简单来说,这只是一种标准的面向对象编码方法:
Command.命令不返回值.Query.查询不会修改数据.遵循命令查询API将为您带来以下好处:
但是命令查询API由于某种原因而存在,而且确实读得更好.那么我们如何获得流畅的界面和命令查询API的好处呢?
答:必须在命令查询API之上实现流畅的接口(而不是通过流畅的接口替换命令查询API ).将流畅的界面视为命令查询API的外观.毕竟,它被称为流畅的" 界面 " - 一个比标准(命令查询)API更可读或更方便的界面.
通常,在命令查询API准备好(写入,可能经过单元测试,抛光到易于调试)之后,您可以在其上编写流畅的接口软件层.换句话说,流畅的界面通过使用命令查询API来完成其功能.然后,使用流畅的界面(使用方法链接),只要您想要方便和可读性.但是,一旦您想了解实际发生的事情(例如,在调试异常时),您就可以随时深入了解命令查询API - 良好的旧的面向对象代码.
我发现使用方法链接的缺点是在发生NullPointerException任何其他Exception情况时调试代码.假设您有以下代码:
String test = "TestMethodChain";
test.substring(0,10).charAt(11); //This is just an example
然后你会得到String index超出范围:执行上面代码时的异常.当你进入实时情况并且发生这样的事情时,你会得到发生了哪一行错误但是没有链接方法的哪一部分引起它.因此,需要明智地使用它,因为它知道数据将始终存在或错误得到正确处理.
它有它的优点,就像你不需要编写多行代码和使用多个变量.
许多框架/工具像Dozer一样使用它,当我用来调试代码时,我必须查看链的每个部分以找出导致错误的原因.
希望这可以帮助.
您可能想阅读Martin Fowler的Fluent Interface
总结