版权声明:本文为 冬夏 原创文章,可以随意转载,但请注明出处。
生成器模式(Builder)模式,封装一个产品的构造过程,并允许按步骤构造。
生成器模式是日常开发中使用最广的设计模式之一,几乎可以说每个稍微大一点的项目都会用到生成器模式。比如 Android 源码的 AlertDialog,最流行的网络库之一 okhttp 等等。
首先我们看一下生成器模式的 UML 图
生成器模式主要有以下几个优点:
- 将一个复杂对象用创建过程封装起来。
- 允许对象通过多个步骤来创建,并且可以改变过程。
- 向客户隐藏产品内部表现。
- 产品的实现可以替换。
下面我通过一个简单的例子来讲解一下生成器模式的使用过程和优点。
假设我们要创建一个 Pizza 类,这个 Pizza 类有很多参数,比如尺寸,馅料种类,是否切块等。那么就存在这样的问题,如果我们把所有的参数都写在构造函数里,那么构造函数就会非常长,而且如果我们以后想要添加其他参数的话,改起来也会比较麻烦。还有一种方法就是先创建出 Pizza 对象,然后再用 setter 方法设置参数,但是这样有可能会导致有一些参数忘记设置了,并且这种方法会导致线程安全的问题。这个时候我们就可以使用生成器模式了。
代码如下:
public class Pizza {
int size = 0;
int type = 0;
boolean isDiced = false;
private Pizza(){
}
protected void setSize(int size){
this.size = size;
}
protected void setStuffType(int type){
this.type = type;
}
protected void isDiced(boolean isDiced){
this.isDiced = isDiced;
}
public static class Builder{
int size = 0;
int type = 0;
boolean isDiced = false;
public Builder(){
}
public Builder setSize(int size){
this.size = size;
return this;
}
public Builder setStuffType(int type){
this.type = type;
return this;
}
public Builder isDiced(boolean isDiced){
this.isDiced = isDiced;
return this;
}
public Pizza build(){
Pizza pizza = new Pizza();
pizza.setSize(size);
pizza.setStuffType(type);
pizza.isDiced(isDiced);
return pizza;
}
}
}
从代码里我们可以看出几个特点
- Pizza 类的构造函数是私有的,也就是说我们不能直接 new 出一个 Pizza 对象,只能通过 Builder 类的 build 方法构建出 Pizza 对象。
- Builder 类是 Pizza 类的 静态内部类,也就是说我们可以直接创建出 Builder 对象,而不用先创建出 Pizza 对象。
- Builder 类的大部分 setter 方法都和 Pizza 类的 setter 方法一样,但是 Builder 类的 setter 方法是 public 的,而 Pizza 的 setter 方法一般是 private 或者 protected 的。
- 在 Builder 对象的 build 方法被调用时才真正生成 Pizza 对象。我们可以在 build 方法里做一些控制,比如参数合法性检测,必填参数检测等。
- Builder 类的参数和 Pizza 类的参数是一样的,这样无形之中增加了代码的复杂度,也增加了出错的可能行。不过我们可以通过另外的一个参数类 Params 来存放所有参数,具体可以看 Android 源码的 AlertDialog 类。