一、文章前言
我们在java中穿梭时都会不停的构建对象,new对象,但是为什么我却找不到“对象”就像一个“野指针”,仔细想想最有可能的就是没有通过最好的手段去构建对象。下文将会为大家谈谈如何使用builder去构建一个对象。(本文参考《Effective Java》)
二、为什么使用Builder模式
1、传统的创建对象可以使用构造器创建,但是当我们调用构造器时通常需要许多你不想要设置的参数,但是又不得不为它们传值。这个时候如果我们使用重叠构造器可行,但是当有许多参数的时候,客户端的代码就会非常难写,并且很难阅读。
重叠构造器代码如下
public class BuilderPerson {
//必选参数
private final String name;
private final int age;
private final int height;
private final int weight;
//可选参数
private final boolean isMarraying;
private final boolean isHasChildren;
public BuilderPerson(String name, int age) {
this(name,age,0);
}
public BuilderPerson(String name, int age, int height) {
this(name,age,height,0);
}
public BuilderPerson(String name, int age, int height, int weight) {
this(name,age,height,weight,false);
}
public BuilderPerson(String name, int age, int height, int weight, boolean isMarraying) {
this(name, age,height,weight,isMarraying,false);
}
public BuilderPerson(String name, int age, int height, int weight, boolean isMarraying, boolean isHasChildren) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
this.isMarraying = isMarraying;
this.isHasChildren = isHasChildren;
}
}
2、当遇到许多构造器参数的时候,还有第二中代替的办法,即使用JavaBean模式,在这种模式下,调用一个无参的构造器来创建对象,然后调用setter方法来设置每个必要的参数,以及每个相关的可选参数。
JavaBean代码如下
public class BuilderPerson {
//必选参数
private String name;
private int age;
private int height;
private int weight;
//可选参数
private boolean isMarraying;
private boolean isHasChildren;
public BuilderPerson() {
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setHeight(int height) {
this.height = height;
}
public void setWeight(int weight) {
this.weight = weight;
}
public void setMarraying(boolean marraying) {
isMarraying = marraying;
}
public void setHasChildren(boolean hasChildren) {
isHasChildren = hasChildren;
}
}
但是JavaBean模式自身有着严重的缺点,会导致类处于不一致(你new了Test类的两个实例,一个只set了A属性,一个只设置了B属性,这两个实例不一致,你不能保证通过该类的同一个构造器保证构造出来的对象是属性相同的。)的状态。
这时就出现了第三种替代的方法既能像重叠构造器那样的安全性,也能保证代码的可读性即Builder模式。
代码如下
public static class Builder{
//必选参数
private String name;
private int age;
private int height;
private int weight;
//可选参数
private final boolean isMarraying;
private final boolean isHasChildren;
public Builder(boolean isMarraying, boolean isHasChildren) {
this.isMarraying = isMarraying;
this.isHasChildren = isHasChildren;
}
public Builder name(String name) {
name = name;
return this;
}
public Builder age(int age) {
age = age;
return this;
}
public Builder height(int height) {
height = height;
return this;
}
public Builder weight(int weight) {
weight = weight;
return this;
}
public BuilderPerson builderPerson() {
return new BuilderPerson(this);
}
}
}
调用如下
BuilderPerson person = new BuilderPerson.Builder(false,false).
name("张三").age(20).height(180).weight(120).buildPerson();
总结
简而言之,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候,与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构建器也比JavaBeans更加安全。