Item 1里讲到了static factory method,它有时候可以用来替代constructor功能。但是static factory method和constructor有个共同的局限:不能很好地扩展到大量可选参数。这时候需要用到另一种方法:Builder Pattern。
用传统constructor的局限
如果我们用constructor来构造很多参数的类时,代码冗长不易管理。比如:
// constructor pattern - does not scale well!
public class MyClass {
private final int para1; // required
private final int para2; // required
private final int para3; // optional
private final int para4; // optional
private final int para5; // optional
private final int para6; // optional
}
public MyClass(int para1, int para2) {
this(para1, para2, 0);
}
public MyClass(int para1, int para2, int para3) {
this(para1, para2, int para3, 0);
}
public MyClass(int para1, int para2, int para3, int para4) {
this(para1, para2, int para3, para4, 0);
}
public MyClass(int para1, int para2, int para3, int para4, int para5) {
this(para1, para2, int para3, para4, para5, 0);
}
public MyClass(int para1, int para2, int para3, int para4, int para5, int para6) {
this.para1 = para1;
this.para2 = para2;
this.para3 = para3;
this.para4 = para4;
this.para5 = para5;
this.para6 = para6;
}
在使用时如果有些参数不想使用默认值,就要把所有参数都传入constructor,比如:
MyClass myClass = new MyClass(240, 8, 100, 0, 35, 27);
改用Builder Pattern
// Builder Pattern
public class MyClass {
private final int para1;
private final int para2;
private final int para3;
private final int para4;
private final int para5;
private final int para6;
public static class Builder {
// required parameters
private final int para1;
private final int para2;
// optional parameters - initialized to default values
private int para3 = 0;
private int para4 = 0;
private int para5 = 0;
private int para6 = 0;
public Builder() {
this.para1 = para1;
this.para2 = para2;
}
public Builder para3(int val) {
para3 = val;
return this;
}
public Builder para4(int val) {
para4 = val;
return this;
}
public Builder para5(int val) {
para5 = val;
return this;
}
public MyClass build() {
return new MyClass(this);
}
}
private MyClass() {
para1 = builder.para1;
para2 = builder.para2;
para3 = builder.para3;
para4 = builder.para4;
para5 = builder.para5;
para6 = builder.para6;
}
}
在client端的代码就会如下:
MyClass something = new MyClass.Buillder(240, 8)
.para3(100)
.para4(30)
.build();
Builder Pattern缺点
虽然Builder Pattern使用起来非常灵活省时,但是也有几个缺点:
- 为了创建对象,必须先创建它的构造器。在十分注重性能的情况下,可能会成为问题。
- 有点冗长,适合多参数时,比如4个参数或者更多。
Summary
如果class的constructor或者static factory有多个参数,设计这种类的时候,Builder Pattern是不错的选择。
网友评论