使用场景与分析
当一个类的构造方法需要多个参数,并且只有部分是必选的,其它是可选的,此时可以考虑使用建造者模式。
- 传统方案一:重载构造方法
在类中重载多个构造方法,根据使用场景进行选择性传参。
弊端:难以阅读,每次实例化对象时需要仔细查看各个构造方法参数上的区别,并且如果两个参数类型相同,参数传混了还不会报错,难以检查。
- 传统方案二:JavaBean模式
提供空参的构造方法,调用多次set方法进行初始化。
弊端:代码冗余,需要写多行set方法。
- 建造者(Builder)模式
建造者模式不提供公开的构造方法,即不允许通过new关键字实例化对象,必须通过其内部类Builder进行初始化。
Builder的构造方法指明必选参数,安全性高。
链式编程与方法名进行区分赋值,可读性强。
注意:当该类的构造方法被private修饰后,该类就不能有子类了,因为子类被实例化时需要先调用父类的public构造方法。
示例:一个学生类
public class Stu {
private final String name; //姓名,必需
private final int age; //年龄,可选
private final int height; //身高,可选
public static class Builder{ //向外提供静态内部类建造者Builder
private String name;
private int age;
private int height;
public Builder(String name){ //提供内部类构造方法,强调姓名为必需参数
this.name = name;
}
public Builder age(int val){ //可选参数年龄
age = val;
return this;
}
public Builder height(int val){ //可选参数身高
height = val;
return this;
}
public Stu builder(){
//利用内部类可访问外部类的私有构造方法的特性进行实例化
return new Stu(this);
}
}
private Stu(Builder builder){ //私有化外部类的构造方法
this.name = builder.name;
this.age = builder.age;
this.height = builder.height;
}
@Override
public String toString() {
return "Stu{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
测试
public class StuBuilderTest {
public static void main(String[] args) {
//通过链式编程,通过方法名可清晰地实例化一个对象及其所需的初始属性
Stu stu = new Stu.Builder("张三").age(20).height(175).builder();
System.out.println(stu);
//也可只初始化部分属性,相对于重载构造方法更加灵活
stu = stu = new Stu.Builder("李四").builder();
System.out.println(stu);
}
/* 输出结果
Stu{name='张三', age=20, height=175}
Stu{name='李四', age=0, height=0}
*/
}