Setters返回实例引用。图案还是反图案?

时间:2011-10-06 10:52:04

标签: java coding-style design-patterns

我正在考虑代码结构,并考虑了setter。这些曾经是void方法,所以为什么不使用一些可能的返回值,来启用一些新的代码结构?

我的想法是将所有属性setter从void更改为实例引用,因此我们可以按顺序执行setter或其他操作。这是一个例子:

public class MyClass {
    private int foo;
    private String bar;

    public MyClass setFoo(int foo) {
        this.foo = foo;
        return this;
    }

    public MyClass setBar(String bar) {
        this.bar = bar;
        return this;
    }

}

然后在我们可以做的代码中的其他地方:

...
MyClass myInstance = new MyClass();
myInstance.setFoo(auxFoo).setBar(auxBar);
...

这允许在一行中设置所有类属性,这在转换方法中很有用。

甚至:

...
return myInstance.setFoo(auxFoo);

这是我的目标,例如在返回时可以设置错误属性。例如,这可以简化catch块。

修改 在得到一些答案后,我需要补充一下:

  • 问题只是关于setter(不是关于在所有方法中执行此操作),并且不限于链接,而是限于其他用法,例如return示例。
  • 从void到其他东西的变化是否会产生任何问题? 例如,JavaBeans Introspection。
  • 你能看到这样做的优势或劣势吗?

我希望看到一些讨论。

5 个答案:

答案 0 :(得分:12)

这是一种常见的技术,称为Method Chaining。 Hibernate在其Criteria类中使用它,并且存在于其他流行的框架中,例如Wicket。

通常,您必须小心并将其应用于那些您确定永远不需要返回任何内容的void方法。并且不应该在Java Bean中使用它,因为在此问题中已经讨论过:Does Java bean's setter permit return this?

请参阅this related SO question,了解使用此模式时可能有用的一些提示和缺点。

答案 1 :(得分:6)

这是很常见的做法,绝对是一种模式 - 而不是反模式。它通常被称为:

http://en.wikipedia.org/wiki/Fluent_interface

http://en.wikipedia.org/wiki/Method_chaining

一些优秀的库使用它:jQuery和joda-time。

您还可以使用不返回任何内容的end方法指定链的结束时间,或完全执行其他操作 - 在inner static builder的情况下,它会调用构造函数。

我非常喜欢它的价值。

答案 2 :(得分:3)

我认为这种模式有其用途,并没有任何内在错误。

我个人经常使用它。有完善的库使用它,例如Gson。即使不是严格意义上的设定者,Java的StringBuilder.append()在精神上并没有什么不同。

答案 3 :(得分:2)

我不建议这样做,因为很多东西依赖于setter的特定方法签名来允许类似Bean的功能。我不确定,但这可能会阻止诸如spring,或jsf之类的东西,或其他假定像Bean的setter的技术。

答案 4 :(得分:2)

这属于一系列众所周知和公认的模式。

让方法返回引用以便能够调用更多方法的一般思路称为方法链接

此类方法链接的更具体示例是,当使用方法设置用作函数输入的实例的属性时。这在C ++中很流行,被称为命名参数成语