问题引出:
Android developer都写过AlertDialog,用法是先new 一个builder,然后往builder里设置属性的值,最后调用build得到类实例,完成抽象出来的类的实例化。
一个类的实例化为什么不是简单的new 对象,为什么要使用这种builder模式去build呢?
难写、难读、难维护 的重叠构造器:
Dialog中需要设置必要的参数ignorebutton、positivebutton,和可选的title、content、icon参数,这样就存在不止一个构造函数,类似
new Dialog(ignorebutton, positivebutton);
new Dialog(title, ignorebutton, positivebutton);
....
code中常有一个类有多个构造函数,构造函数的参数个数一般递增,层层调用,我们叫他重叠构造器模式(telescoping constructor)。
参数个数少用这个不会有问题,参数个数多了,创建构造函数时,写参数会让人头疼,修改参数会让人很难维护。
易维护、难一致的JavaBean:
使用JavaBean的方式可以避免传参数不知道对应哪个字段、修改参数类型容易对应错的问题。在JavaBean的setter方法中明确了对应的字段和类型。省去了重叠构造方法。
但JavaBean也有他的缺陷, JavaBean对象可以随时调用setter方法进行设置,这会让Bean缺乏一致性、也就是类的实例的一致性没法保证了。特别是在多线程情况下,会出现很难分析的bug。
1 class Bean{
2 int x,
3 int y,
4 setx(){}
5 setY(){}
6 }
保证了一致性、灵活性的Builder对象:
Builder模式解决了JavaBean一致性的问题, 在Bean中创建内部Builder类,使用Builder中类似setter的方法设置对应的属性给Builder。然后通过public Bean build(){}方法,实例化Bean对象并返回给客户调用者,重要的是这个Bean对象是确定下来的, 而且Builder模式的灵活性,可以通过不同的setter生成多个自定义的Bean对象。
class Bean{
class Builder{
int x;
int y;
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public Bean build(){
return new Builder();
}
}
}
客户使用Builder模式的方式:
Bean bean = (new Bean.Builder()).setX(8).setY(9).build();
Bean bean2 = (new Bean.Builder()).setX(1).setY(2).build();
bean和Bean2是2个完全独立的对象,而且每个单独的对象一旦创建不会存在变化导致的线程安全问题。