当构造方法参数过多时使用build模式

Posted origalom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当构造方法参数过多时使用build模式相关的知识,希望对你有一定的参考价值。

  静态工厂方法和构造方法都有同一个缺陷:当可选参数过多时,它们都没有办法很好的进行扩展。所以,当参数过多时,一般采用的方法有:可伸缩构造方法模式(the telescoping constructor pattern)、javaBeans模式和Builder模式。

1、telescoping constructor模式

  (1)如何使用

    在telescoping constructor模式中,首先提供一个必需参数的构造方法,然后再加一个可选参数形成第二个构造方法,接着再加一个可选参数形成第三个构造方法,等等,直到构造方法中包含所有的可选参数。例如:

 1 public class Person {
 2     private String name;          // 必需
 3     private String nickname;    // 必需
 4     private int age;                  // 可选
 5     private String phone;         // 可选
 6 
 7     public Person(String name, String nickname) {
 8        this(name, nickname, 0);
 9     }
10 
11     public Person(String name, String nickname, int age) {
12        this(name, nickname, age, null);
13     }
14 
15     public Person(String name, String nickname, int age, String phone) {
16        this.name = name;
17        this.nickname = nickname;
18        this.age = age;
19        this.phone = phone;
20     }
21 }

  实例化方法:Person p = new Person("张三", "小小");

  (2)缺点

    • 当对象实例化时,你可能会需要对你不想设置的参数传值
    • 当参数很多时,客户端代码很难编写,也很难进行阅读

2、JavaBeans模式

  (1)如何使用

    在JavaBeans模式中,先调用一个无参构造方法创建对象,然后调用类中的setter方法设置参数。例如:

 1 public class Person {
 2      private String name;          // 必需
 3      private String nickname;    // 必需
 4      private int age;                  // 可选
 5      private String phone;         // 可选
 6 
 7      public Person() {}
 8 
 9      public void setName(String name) {
10        this.name = name;
11      } 
12 
13      public void setNickname(String nickname) {
14         this.nickname = nickname;
15      }
16 
17      public void setAge(int age) {
18         this.age = age;
19      }
20 
21      public void setPhone(String phone) {
22        this.phone = phone;
23      }
24 }

  实例化方法: Person p = new Person();

         p.setName("张三");

         p.setNickname("小小");

  (2)缺点

    由于构造方法在多次调用中被分割,所以JavaBeans模式是线程不安全的,在多线程模式下,对象的值可能会发生变化。

3、Builder模式

  (1)如何使用

    builder模式结合了telescoping constructor模式的安全性和JavaBeans模式的可读性。客户端不直接调用所需对象,而是使用所有必须参数的构造方法(或静态工厂方法)来获取一个bulider对象;然后客户端调用builder对象的和setter相似的方法来设置每个可选参数;最后,客户端调用一个无参的builder方法来生成一个对象。

 1 public static class Pizza {
 2     public enum Topping {HAM, MUSHROOM, ONION}
 3     final Set<Topping> toppings;
 4 
 5     abstract static class Builder<T extends Builder<T>> {
 6         EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
 7         public T addTopping(Topping topping) {
 8             toppings.add(topping);
 9             return self();
10         }
11         abstract Pizza build();
12 
13         protected abstract T self();
14     }
15 
16     Pizza(Builder<?> builder) {
17         toppings = builder.toppings.clone();
18     }
19 }
20 
21 public class MyPizza extends Pizza {
22     public enum Size{SMALL, MEDIUM, LARGE}
23     private final Size size;
24 
25     public static class Builder extends Pizza.Builder<Builder> {
26         private final Size size;
27 
28         public Builder(Size size) {
29             this.size = size;
30         }
31 
32         @Override
33         public MyPizza build() {
34             return new MyPizza(this);
35         }    
36 
37         @Override
38         protected Builder self() {
39             return this;
40         }
41     }
42 
43     private MyPizza(Builder builder) {
44         super(builder);
45         size = builder.size;
46     }
47 }

 

   实例化方法:MyPizza pizza = new MyPizza.Builder(SMALL).addTopping(SAUAGE).build();

  (2) 缺点

    为了创建对象,必须先创建对象的builder,所以在关键的时候,性能会有稍许影响,而且builder模式的构建比较麻烦。

4、总结

  当设计类的构造方法或静态工厂的参数超过几个时,Builder模式是一个不错的选择,特别是如果许多参数是可选的或相同类型的。

 

以上是关于当构造方法参数过多时使用build模式的主要内容,如果未能解决你的问题,请参考以下文章

详解 Scala 模式匹配

Builder模式

用静态工厂方法代替构造器遇到多个构造器参数时要考虑用构建器

当我们将对象作为参数传递给方法时,为啥会调用复制构造函数?

Javascript this的值

当具体对象采用不同的构造函数参数时,Java 中的工厂