设计:Java和在setter方法中返回自引用

时间:2020-03-05 18:44:13  来源:igfitidea点击:

我已经在博客中提出了这个建议,但是我觉得这个地方最合适。

对于具有经常使用的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();