一,概念
Java类的构建器是用来构造类的实例的,它能够让编程人员以一种非常灵活的方式构造不同形态的对象.
有人会疑问,类的对象不是通过调用构造方法创建的吗?其实归根结底,构建器是通过调用构造方法来生成对象的.
构建器的作用:
1,增强代码的可读性及减少代码的维护成本;
2,减少设计一个类时构造方法的个数.
假设有一个类People,它有很多的属性,如 name,sex,age,address,height,weight,job,company....;然而当我们构造People的对象时,可能一下子并不需要(也不确定需要)哪些属性.但是构造方法的参数是确定的,如果我们在实际的编程中要通过重载构造方法,通过传入构造方法的参数的不同来生成不同形态的对象,那么就要写很多接收参数不同的构造方法,这对编程人员来说是很痛苦的一件事,因为代码会因此显得不简洁自然,好的代码,应该是让人感觉很舒服,很简洁和自然的.
下面通过设计一个没有构建器的类PeopleWithNoBuilder和一个有构建器的类PeopleWithBuilder来看看构建器这两点作用的体现,假设属性name是构造对象时必需的属性:
public class BuilderTest {
public static void main(String[] args) {
String name = "jarip";
String sex = "male";
int age = 100;
String address = "shenzhen";
int height = 100;
int weight = 100;
String job = "it";
String company = "kd";
//构造不使用Builder方式设计的People类的实例
PeopleWithNoBuilder p1 = new PeopleWithNoBuilder(name,sex,age);
PeopleWithNoBuilder p2 = new PeopleWithNoBuilder(name,job,company);
PeopleWithNoBuilder p3 = new PeopleWithNoBuilder(name,sex,age,height,weight);
//下面的构造方法已注释,不可调用
//PeopleWithNoBuilder p4 = PeopleWithNoBuilder(name,sex,address);
//构造使用Builder方式设计的People类的实例
PeopleWithBuilder pb1 = new PeopleWithBuilder.Builder(name).sex(sex).age(age).build();
PeopleWithBuilder pb2 = new PeopleWithBuilder.Builder(name).job(job).company(company).build();
PeopleWithBuilder pb3 = new PeopleWithBuilder.Builder(name).sex(sex).age(age).height(height).weight(weight).build();
PeopleWithBuilder pb4 = new PeopleWithBuilder.Builder(name).sex(sex).address(address).build();
//输出构造结果
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
System.out.println(pb1);
System.out.println(pb2);
System.out.println(pb3);
System.out.println(pb4);
}
}
/**
* 不使用Builder方式设计的People类
*/
class PeopleWithNoBuilder{
private String name;
private String sex;
private int age;
private String address;
private int height;
private int weight;
private String job;
private String company;
/**
* 构造方法
* @param name 名字
* @param sex 性别
* @param age 年龄
*/
public PeopleWithNoBuilder(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
/**
* 构造方法
* @param name 名字
* @param job 工作
* @param company 公司
*/
public PeopleWithNoBuilder(String name, String job, String company) {
this.name = name;
this.job = job;
this.company = company;
}
/**
* 构造方法
* @param name 名字
* @param sex 性别
* @param age 年龄
* @param height 身高
* @param weight 体重
*/
public PeopleWithNoBuilder(String name, String sex, int age, int height,
int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.height = height;
this.weight = weight;
}
@Override
public String toString() {
return "PeopleWithNoBuilder [name=" + name + ", sex=" + sex + ", age="
+ age + ", address=" + address + ", height=" + height
+ ", weight=" + weight + ", job=" + job + ", company="
+ company + "]";
}
//去掉注释后,下面这个构造方法编译不能通过,因为参数列表的类型顺序
//与PeopleWithNoBuilder(String name, String job, String company)方法相同
/**
* 构造方法
* @param name 名字
* @param sex 性别
* @param address 住址
*/
/*public PeopleWithNoBuilder(String name, String sex, String address) {
this.name = name;
this.sex = sex;
this.address = address;
}*/
}
/**
* 使用Builder方式设计的People类
*/
class PeopleWithBuilder{
private String name;
private String sex;
private int age;
private String address;
private int height;
private int weight;
private String job;
private String company;
public static class Builder{
private String name;
private String sex;
private int age;
private String address;
private int height;
private int weight;
private String job;
private String company;
/**
* Builder构造方法,传入必需的name属性
* @param name
*/
public Builder(String name){
this.name = name;
}
public Builder sex(String sex){
this.sex = sex;
return this;
}
public Builder age(int age){
this.age = age;
return this;
}
public Builder address(String address){
this.address = address;
return this;
}
public Builder height(int height){
this.height = height;
return this;
}
public Builder weight(int weight){
this.weight = weight;
return this;
}
public Builder job(String job){
this.job = job;
return this;
}
public Builder company(String company){
this.company = company;
return this;
}
public PeopleWithBuilder build(){
return new PeopleWithBuilder(this);
}
}
private PeopleWithBuilder(Builder builder){
this.name = builder.name;
this.sex = builder.sex;
this.age = builder.age;
this.address = builder.address;
this.height = builder.height;
this.weight = builder.weight;
this.job = builder.job;
this.company = builder.company;
}
@Override
public String toString() {
return "PeopleWithBuilder [name=" + name + ", sex=" + sex + ", age="
+ age + ", address=" + address + ", height=" + height
+ ", weight=" + weight + ", job=" + job + ", company="
+ company + "]";
}
}
由上面的代码还可以看出,当一个类的属性有很多,并且在实际情况中要构造很多不同形态的对象时,应该考虑用构建器代替一堆的构造方法来产生对象;因为构建器不但能像构造方法那样在生成对象之际就把所有需要赋值的属性赋好值,而且还可以克服构造方法的设计中由于参数列表的类型和顺序一致而造成的无法重载等等问题,可以灵活地定制编程人员所需要的对象.
而有的时候,有的程序员会用下面的方式代替构建器:
class PeopleWithBuilderAnother{
private String name;
private String sex;
private int age;
private String address;
private int height;
private int weight;
private String job;
private String company;
public PeopleWithBuilderAnother(String name){
this.name = name;
}
public PeopleWithBuilderAnother setName(String name) {
this.name = name;
return this;
}
public PeopleWithBuilderAnother setSex(String sex) {
this.sex = sex;
return this;
}
public PeopleWithBuilderAnother setAge(int age) {
this.age = age;
return this;
}
public PeopleWithBuilderAnother setAddress(String address) {
this.address = address;
return this;
}
public PeopleWithBuilderAnother setHeight(int height) {
this.height = height;
return this;
}
public PeopleWithBuilderAnother setWeight(int weight) {
this.weight = weight;
return this;
}
public PeopleWithBuilderAnother setJob(String job) {
this.job = job;
return this;
}
public PeopleWithBuilderAnother setCompany(String company) {
this.company = company;
return this;
}
}
获取对象则用下面的方式:
PeopleWithBuilderAnother pa = new PeopleWithBuilderAnother(name).setSex(sex).setAge(age);
这里要说的是,无论是用构建器的方式,还是用上面这种方式,都没有绝对的好坏之分,假如觉得用构建器方式获取对象时还要先生成构建器对象(Builder实例)会造成较大的开销,那么使用这种方式也可以,不过需要注意的是,上面的这种设计让set方法的作用泛化了,因为在这里set方法可以用来在构造对象时给属性赋值,也可以在构造对象之后改变属性的值;而采用构建器的方式时,Builder里面的给所有属性赋值的方法都是为生成PeopleWithBuilder对象而存在,其作用是明确的.