建造者模式的变种是目前用得比较多的,各大SDK初始化的时候基本都会使用建造者模式。经典的建造者模式重点在于抽象出对象创建的步骤,并通过调用不同的具体实现从而得到不同的结果。而变种的建造者模式目的在于减少对象在创建过程中引入的多个重载构造函数,可选参数以及Set方法的过度使用导致的不必要复杂性,变种的建造者模式更加适用于参数多的对象,并且这些参数中有部分参数是可选的,有部分参数是必传的。下面我们就以构建一个人(Person)的例子介绍变种的建造者模式。
public class Person {
private final String mName; // 姓名,必填
private final String mGender; // 性别,必填
private final int mAge; // 年龄,可选
private final String mPhoneNo; // 电话,可选
private final String mWeight;// 体重,,可选
public Person(String mName,
String mGender,
int mAge,
String mPhoneNo,
String mWeight) {
this.mName = mName;
this.mGender = mGender;
this.mAge = mAge;
this.mPhoneNo = mPhoneNo;
this.mWeight = mWeight;
}
public Person(String mName,
String mGender,
int mAge,
String mPhoneNo) {
this(mName, mGender, mAge, mPhoneNo, "");
}
public Person(String mName,
String mGender,
int mAge) {
this(mName, mGender, mAge, "", "");
}
}
在上面的类中,我们的姓名和性别是必选项,其他是可选项,为了能够实现必选和可选的功能,我们需要在类中定义多个重载构造函数,来满足我们的需求,或者是给提供set和get方法,让必选项的参数通过构造函数传递,但是参数很多的时候就会很复杂了,传递参数的时候特别头痛。所以出现了变种的建造者模式。代码如下:
public class PersonB {
private final String mName; // 姓名
private final String mGender; // 性别
private final int mAge; // 年龄
private final String mPhoneNo; // 电话
private final String mWeight;// 体重
private PersonB(PersonBuilder builder){
mName = builder.name;
mGender = builder.gender;
mAge = builder.age;
mPhoneNo = builder.phoneNo;
mWeight = builder.weight;
}
public String getName() {
return mName;
}
public String getGender() {
return mGender;
}
public int getAge() {
return mAge;
}
public String getPhoneNo() {
return mPhoneNo;
}
public String getWeight() {
return mWeight;
}
@Override
public String toString() {
return "PersonB{" +
"mName='" + mName + '\'' +
", mGender='" + mGender + '\'' +
", mAge=" + mAge +
", mPhoneNo='" + mPhoneNo + '\'' +
", mWeight='" + mWeight + '\'' +
'}';
}
public static class PersonBuilder {
private final String name; // 姓名
private final String gender; // 性别
private int age; // 年龄
private String phoneNo; // 电话
private String weight;// 体重
public PersonBuilder(String name,String gender){
this.name = name;
this.gender = gender;
}
public PersonBuilder age(int age){
this.age = age;
return this;
}
public PersonBuilder phone(String phoneNo){
this.phoneNo = phoneNo;
return this;
}
public PersonBuilder weight(String weight){
this.weight = weight;
return this;
}
public PersonB build(){
return new PersonB(this);
}
}
}
观察上面的类我们可以发现,首先我们需要构造的对象PersonB的构造函数是私有的,意味着调用者无法直接通过实例化获取PersonB 的对象,其次PersonB类里面的属性是final的并且在构造函数中设置,对外只提供get方法,即调用者只能用,不能改。最后通过PersonBuilder的构造函数接收必选参数,其他的属性可以通过PersonBuilder提供的方法设置,其中每个方法都会返回当前的PersonBuilder对象,这样可以让我们设置参数的时候使用链式调用,如下所示:
public PersonBuilder age(int age){
this.age = age;
return this;
}
最后,我们可以看下如何使用变种的建造者模式:
public class Client {
public static void main(String[] args) {
// 构建一个Person
PersonB personB = new PersonB.PersonBuilder("职场007","male")
.age(28)
.phone("1234567890")
.weight("83kg")
.build();
System.out.println("构建者模式构建出的对象: " + personB);
}
}
运行结果: