让java中的setter返回“this”是好还是坏?
public Employee setName(String name){
this.name = name;
return this;
}
这个模式很有用,因为你可以像这样设置链:
list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));
而不是这样:
Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);
...但这有点违背标准惯例。我认为这是值得的因为它可以让setter做一些其他有用的事情。我曾在一些地方看到过这种模式(例如JMock、JPA),但它似乎并不常见,而且通常只用于定义良好的api,在这些api中这种模式随处可见。
更新:
我所描述的显然是有效的,但我真正想要的是一些关于这是否被普遍接受的想法,以及是否存在任何陷阱或相关的最佳实践。我知道Builder模式,但它比我所描述的要复杂一些——正如Josh Bloch所描述的,有一个用于对象创建的相关静态Builder类。
总结:
它被称为“流畅接口”或“方法链接”。
这不是“标准”Java,尽管你现在看到的越来越多(在jQuery中工作得很好)
它违反了JavaBean规范,因此它将与各种工具和库分开,特别是JSP构建器和Spring。
它可能会阻止JVM通常会做的一些优化
一些人认为它能清理代码,另一些人认为它“可怕”
还有一些没有提到的要点:
This violates the principal that each function should do one (and only one) thing. You may or may not believe in this, but in Java I believe it works well.
IDEs aren't going to generate these for you (by default).
I finally, here's a real-world data point. I have had problems using a library built like this. Hibernate's query builder is an example of this in an existing library. Since Query's set* methods are returning queries, it's impossible to tell just by looking at the signature how to use it. For example:
Query setWhatever(String what);
It introduces an ambiguity: does the method modify the current object (your pattern) or, perhaps Query is really immutable (a very popular and valuable pattern), and the method is returning a new one. It just makes the library harder to use, and many programmers don't exploit this feature. If setters were setters, it would be clearer how to use it.
这一点也不坏。但是它与JavaBeans Spec不兼容。
有很多规范依赖于这些标准访问器。
你总能让它们共存。
public class Some {
public String getValue() { // JavaBeans
return value;
}
public void setValue(final String value) { // JavaBeans
this.value = value;
}
public String value() { // simple
return getValue();
}
public Some value(final String value) { // fluent/chaining
setValue(value);
return this;
}
private String value;
}
现在我们可以一起用了。
new Some().value("some").getValue();
下面是另一个版本的不可变对象。
public class Some {
public static class Builder {
public Some build() { return new Some(value); }
public Builder value(final String value) {
this.value = value;
return this;
}
private String value;
}
private Some(final String value) {
super();
this.value = value;
}
public String getValue() { return value; }
public String value() { return getValue();}
private final String value;
}
现在我们可以这么做了。
new Some.Builder().value("value").build().getValue();