出现此模式的原因:当我们需要建造一个复杂对象时候,我们需要提高可读性和方便性的时候,此模式就孕育而生了。
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
代码示例:
public class BuildBean {
public final String name;
public final String age;
private BuildBean(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
@Override
public String toString() {
return "BuildBean{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
public static class Builder{
private String name;
private String age;
public BuildBean.Builder setName(String name){
this.name = name;
return this;
}
public BuildBean.Builder setAge(String age){
this.age = age;
return this;
}
public BuildBean build(){
return new BuildBean(this);
}
public Builder(){}
}
}
个人理解有以下几个关键点:
- 被构建者BuildBean 的构造方法是私有的——防止用户通过builder以外的方式创建被构建者;
- 构建者Builder 的构造方法是public的——给用户通过builder方式创建被构建者;
- 被构建者只提供get方法,构建者只提供set方法——这是职责分明的意思,把构建和表达分开;
- 被构建者的属性加上final 修饰——这个可加可不加,加了更好,因为被构建者只有私有构造方法;
运用示例:
// 第一中写法
BuildBean.Builder builder = new BuildBean.Builder();
builder.setAge("12122");
builder.setName("sfdsdf");
BuildBean buildBean = builder.build();
// 二
BuildBean buildBean2 = new BuildBean.Builder()
.setName("adcc")
.setAge("00")
.build();
对于第二种写法,不能先build 在调用build方法,因为build方法返回的是被构建者BuildBean,BuildBean 是没有set方法的。
build模式核心思想
我们先看一个简单代码
public class GetSelf {
public GetSelf(){}
public GetSelf get(){
// 插入一些其他逻辑
return this;
}
public static void main(String[] args) {
GetSelf getSelf = new GetSelf();
System.out.println(getSelf.get().toString());
}
}
这里只有一个默认构造方法,和一个get方法返回this;然后测试打印get获取的对象,运行ok没有问题。现在我们就想想,这个简单demo,说明了什么,其实就是get方法返回的this ,这个this 很神奇,它表示自己,先把自己构建出来,然后通过get方法返回自己,看看前面build ,是不是就是这种思想,有种豁然开朗的感觉,我自己之前一直很疑惑为啥要返回this,这个this又是啥,从哪里来,怎么赋值的?
现在知道了,这里 通过 new BuildBean.Builder() 方法创建构建者本身,然后再一一给属性赋值,在最后通过build()方法创建被构建者,并把之前的属性值带过去通过被构建者的构造方法赋值属性。
场景运用
build模式在很多地方会用,比如AlertDialog,ImageLoader的options的创建,Okhttp的实例对象,retofit的实例对象等等,现在开始,也开始尝试运用吧。