在介绍构建器之前先来看看Java创建对象并初始化参数的两种方式:
已Person类为例。
class Person{
// 以下必要参数
public int weight;
public int height;
public String sex;
public int age;
// 以下是可选参数
public String location;
public String wife;
public String phone;
public String name;
}
1、通过构造方法:
private Person(int weight,int height,String sex,int age,String location,String wife,String phone,String name){
this.weight = weight;
this.height = height;
this.sex = sex;
this.age = age;
this.location = location;
this.wife = wife;
this.phone = phone;
this.name = name;
}
实例化对象:
Person p = new Person(23, 12, "0", 2, "NJ", "", "", "");
这样的方式会导致你不想设置的参数,也不得不给他们传值,当参数再多的时候操作起来就比较麻烦了,而且还要对照参数的对应关系。
2.通过先实例化对象,再设置参数
Person p = new Person();
p.weight =34;
p.height = 23;
p.sex = "0";
p.location = "NJ";
这种就是JavaBeans模式,参数的构造过程被分开了,JavaBean可能会处于一个不一致的状态;阻止了把类变成不可变的可能,需要保证线程的安全。
3.第三种就是主要介绍的利用构建器实例化对象:不直接生成对象,而是让客户端利用所有必要的参数调用构造器,得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法来生成不可变的对象。这个builder是它构建的类的静态成员类。
class Person{
// 以下必要参数
public int weight;
public int height;
public String sex;
public int age;
// 以下是可选参数
public String location;
public String wife;
public String phone;
public String name;
// 内部类 构建器
public static class Builder{
private int weight;
private int height;
private String sex;
private int age;
private String location;
private String wife;
private String phone;
private String name;
// Person必须参数作为构造函数的参数
public Builder(int w,int h,String s,int a){
weight = w;
height = h;
sex = s;
age = a;
}
// 可选参数以方法形式设置 返回Builder是为了能把参数链接起来
public Builder location(String l){
location = l;
return this;
}
public Builder wife(String w){
wife= w;
return this;
}
public Builder phone(String p){
phone = p;
return this;
}
public Builder name(String n){
name = n;
return this;
}
// 调用Person的构造方法,把builder的内容设置给Person
public Person build(){
return new Person(this);
}
}
private Person(Builder b){
weight = b.weight;
height = b.height;
sex = b.sex;
age= b.age;
location = b.location;
wife = b.wife;
phone = b.phone;
name = b.name;
}
}
客户端实例化代码:
Person p = new Person.Builder(20, 30, "0", 0).location("NJ").name("大师兄").build();
总结:个人认为实现的思路就是,通过builder接收所有参数然后作为一个对象给目标对象,目标对象获取所有属性。
这种方式带来的好处:1.保证了类的一致性2.客户端代码容易编写,特别是可选参数设置的灵活性,易于阅读 ;相应也会有一些不足:为了创建对象,必须要先创建 构建器,增加了一个对象的成本,在十分注重性能的系统上可能会成为问题;这种模式还比重叠构造器更加 冗长,但是如果给类增加参数就会很方便。
简而言之,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候。与使用传统的重叠构造器模式相比,使用builder模式的客户端代码讲更易于阅读与编写,构造器也比Javabeans更加安全。