设计:Java和在setter方法中返回自引用
我已经在博客中提出了这个建议,但是我觉得这个地方最合适。
对于具有经常使用的setter列表的类,我发现这种方式非常有用(尽管最近我读到了Effective Java中的Builder模式也差不多)。
基本上,所有的setter方法都返回对象本身,因此我们可以使用如下代码:
MyClass .setInt(1) .setString("test") .setBoolean(true);
设置员最后只返回以下内容:
public MyClass setInt(int anInt) { // [snip] return this; }
你有什么意见?优缺点都有什么?这对性能有影响吗?
解决方案
回答
我自己不会这样做,因为对我来说,它会混淆特定方法的工作,并且方法链对我的长期使用是有限的。不过,这不会让我陷入愤怒和精神病的颤抖的球中,这始终是一件好事。 :')
我不会担心性能;只是问克努斯。
回答
供参考,这称为Fluent接口。
就个人而言,我认为这是一个很好的主意,但实际上是一个品味问题。我认为jQuery以这种方式工作。
回答
我同意@Bernard的观点,即像这样的方法链接会混淆设置者的目的。相反,我建议如果我们始终创建这样的二传手链,则应为类创建一个自定义构造函数,这样就可以代替
MyClass .setInt(1) .setString("test") .setBoolean(true) ;
你做
new MyClass(1,"test",true);
这使它更具可读性,并且如果我们愿意,可以使用它使类不可变。
回答
这个想法在c ++中经常见到,它允许级联操作...
例如
std::cout << "this" << "is" << "cascading"
是流方法<<返回其自身实例(* this)的地方。
参见:http://www.java2s.com/Tutorial/Cpp/0180__Class/Cascadingmemberfunctioncallswiththethispointer.htm
回答
我发现在二传手中使用时,这种方式风格很差。不可变类通常更适合链接,例如:
aWithB = myObject.withA(someA).withB(someB);
其中myObject是此类的:
class MyClass { withA(TypeA a) { this.a.equals(a) ? this : new MyClass(this, a); } private MyClass(MyClass copy, TypeA a) { this(copy); this.a = a; } }
构建器模式也很有用,因为它允许最终对象不可变,同时防止使用该技术时通常必须创建的中间实例。
回答
我曾经是Java(甚至更糟糕的C#)实践的迷,该实践在整个对象中进行getter和setter(获取set属性)。这曾经是我认为是面向对象的,但实际上,这导致我们仅了解对象的内胆和实现,而没有真正利用封装。有时我们可能无法摆脱这一点(想到OR / M),但是通常应该先设置对象,然后执行其功能。我梦想中的对象倾向于具有一两个构造函数,并且可能有六个起作用的函数。
这样做的原因是,一旦我开始开发API,就真的需要使事情保持简单。我们确实只想增加完成工作所需的复杂度,而getter和setter本身虽然很简单,但是在大量添加时会增加堆的复杂性。当我以不同的顺序加载设置器时会发生什么?有什么不同吗?你确定吗?
回答
再次@Dan,对于更复杂的情况(牢记不变性),Builder Pattern是一个很好的解决方案。
另外,我也很赞同你的观点。我相信意思是主要遵循"不要问"的范例,我非常同意。但这主要是针对吸气剂。
最后,以上所有都是针对具有大量属性的类的。如果我们只有少于7个的字符,我看不出有任何原因。
回答
@pek
链式调用是Java 7的建议之一。它表示,如果方法返回类型为void,则应隐式返回该方法。如果我们对此主题感兴趣,Alex Miller的Java 7页面上有很多链接和一个简单示例。
回答
在使用Apache POI excel库时,我最终做了很多事情。我最终写了链接的帮助程序方法,因此可以应用格式设置,数据类型,内部单元格数据,公式和单元格定位。
对于具有许多需要进行细微调整的小重量级元素的东西,它的效果很好。
回答
对于构建者而言,这是有意义的,我们要做的就是设置工作负载,创建实际对象并将构建者扔掉。对于构建者,我们也可以摆脱方法名称的"设置"部分。同样,不可变类型实际上并不需要" get"。
Something thing = new SomethingBuilder() .aProperty(wotsit) .anotherProperty(somethingElse) .create();
一个有用的技巧(如果我们不介意每个类约2K的运行时开销)是使用双括号习惯用法:
JFrame frame = new JFrame("My frame") {{ setDefaultCloseOperation(DISPOSE_ON_CLOSE); setLocation(frameTopLeft); add(createContents()); pack(); setVisible(true); }};
回答
如何使用
/** * * @author sanjay */ public class NewClass { private int left ; private int top; public void set(int x,int y) { left=x; top=y; } public NewClass UP(int x) { top+=x; return this; } public NewClass DOWN(int x) { top-=x; return this; } public NewClass RIGHT(int x) { left+=x; return this; } public NewClass LEFT(int x) { left-=x; return this; } public void Display() { System.out.println("TOP:"+top); System.out.println("\nLEFT\n:"+left); } } public static void main(String[] args) { // TODO code application logic here NewClass test = new NewClass(); test.set(0,0); test.Display(); test.UP(20).UP(45).DOWN(12).RIGHT(32).LEFT(20); test.Display();