Java:为什么使用方法而不是构造函数?

时间:2017-06-20 06:15:32

标签: java design-patterns

假设您有一个名为Person的班级,Personnameidage等属性,而不是设置这些构造函数中的值,一个

new Person().withName("Lorem").withId("1234").withAge(29)

with方法是对set方法的调用,并返回该对象,例如,

public Person withAge(int age) {
    this.setAge(age);
    return this;
}

在当前项目中,我看到很多这样的代码,通常会对不同的with方法进行5-10个链式调用。这样做有什么好处,而不是在构造函数中设置这些值?

4 个答案:

答案 0 :(得分:3)

  

这样做有什么好处,而不是在构造函数中设置这些值?

1)超载

如果要设置大量参数,可以轻松管理要设置的值的数量,但有些是可选的,您不必创建特定的构造函数或传递null值。 / p>

 new Person("name", 19);
 new Person("name", 19, address);

 new Person("name", 19, phone);

(那些是不好的例子;))

在你的情况下,你只需要调用你需要的方法(与setter相同)。

2)身份认同

此外,在方法/构造函数中包含大量参数往往难以阅读,以识别每个参数上下文

 new Person("frank", "John", "Emma");
 person.withName("frank").withFather("john").withMother("Emma");

将参数传递给方法/构造函数是无名的,您必须检查签名以了解您传递的内容。使用该表示法,您可以获得更详细和可读的代码。 (再次,与setter相同)。

3)可连接的二传手 使用setter也是如此,但没有你在这里的可链接功能。

person.setName("name");
person.setAge(19);

person.withName("name").withAge(19);

除了可读性之外,我认为没有真正的改进,链需要方法来返回实例本身,在类本身中提供重新生成代码({{1 }})。

答案 1 :(得分:2)

我看到的一个优点是可读性。

如果我们扩展示例

new Person()
.withName("Lorem")
.withId("1234")
.withAge(29)
.withHeight(170)
.withWeight(75)
.withTaxId("1234");

如果我们没有使用这种模式并使用了构造函数模式,那么在使用它们时我们会得到很多参数而没有任何关于它们的描述。

new Person("Lorem","1234",29,170,75,"1234");

答案 2 :(得分:2)

关于可读性和fluent interfaces

虽然您的示例对于流畅的界面不是很好,但您可以在Java part of the wikipedia article:中找到:

Author author = AUTHOR.as("author");
create.selectFrom(author)
      .where(exists(selectOne()
                   .from(BOOK)
                   .where(BOOK.STATUS.eq(BOOK_STATUS.SOLD_OUT))
                   .and(BOOK.AUTHOR_ID.eq(author.ID))));

流畅的接口是API设计中一个非常高级的主题,通常带有某种Builder patternto avoid too big and too many constructors)或Facade pattern(以避免难以理解,主要是内部API )。

漂亮流畅的API通常需要深入了解您的要求和非常好的计划/准备阶段。

请注意,使用流畅的API与编写DSL密切相关。这里有一个Martin Fowler的例子和一个扩展的,really good explanation流畅的接口,它的优点,缺点,理论等。

答案 3 :(得分:1)

似乎有两大优势:

1。)灵活性:使用此模式,您基本上可以选择填充而不填充的字段。使用构造函数时,您需要具有多个构造函数才能实现相同的功能。正如在std.textio中可以

Person

或者它可以是

new Person().withName("Loren")

其他一切都为null / default。

如果是构造函数初始化,则必须为这两个构造函数提供2个构造函数。

new Person().withName("Loren").withAge(30)

2。)正如其他答案所述,可读性。

public Person(String name){
  //code
}

public Person(String name, String age){
//code
}

更具可读性
new Person().withName("Loren").withAge(30).withId(567)