一、基础知识:先前学习建造者模式的时候,总是以这个UML图作为学习基础资料

Design Pattern ——Builder-LMLPHP

然后总是要记住四个角色

  • 产品类:一般是一个较为复杂的对象,也就是说创建对象的过程比较复杂,一般会有比较多的代码量。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。
  • 抽象建造者:引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。
  • 建造者:实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。
  • 导演类:负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。住四然后总是要记住四个角色

我们可以看到,建造者模式相对工厂方法模式,更加注重产品建造过程,个人认为这才是Builder的核心思想。

二、近日看了一些Builder的例子,再一次觉得设计模式很多时候是一种思想,而不是照搬UML图

例子1.

 public class User {
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
} public String getFirstName() {
return firstName;
} public String getLastName() {
return lastName;
} public int getAge() {
return age;
} public String getPhone() {
return phone;
} public String getAddress() {
return address;
} public static class UserBuilder {
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address; public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
} public UserBuilder age(int age) {
this.age = age;
return this;
} public UserBuilder phone(String phone) {
this.phone = phone;
return this;
} public UserBuilder address(String address) {
this.address = address;
return this;
} public User build() {
return new User(this);
} }
}

当我们试图创建一个user对象的时候

 public User getUser() {
return new
User.UserBuilder('Jhon', 'Doe')
.age(30)
.phone('1234567')
.address('Fake address 1234')
.build();
}

优点如下:

  • User构造方法是私有的,这意味着该类不能在客户端代码里直接实例化。
  • User所有属性都是final类型的,在构造方法里面被赋值。只提供了getter方法。
  • builder类使用流式接口风格,让客户端代码阅读起来更容易(见getUser())。
  • builder类构造方法只接收必须属性,为了确保这些属性在构造方法里赋值,只有这些属性被定义成final类型。

另外还有一个例子:

AlertDialog

 public class AlertDialog extends Dialog implements DialogInterface {

     ...

     protected AlertDialog(Context context, int theme) {
this(context, theme, true);
} AlertDialog(Context context, int theme, boolean createThemeContextWrapper) {
super(context, resolveDialogTheme(context, theme), createThemeContextWrapper); mWindow.alwaysReadCloseOnTouchAttr();
mAlert = new AlertController(getContext(), this, getWindow());
} protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, resolveDialogTheme(context, 0));
mWindow.alwaysReadCloseOnTouchAttr();
setCancelable(cancelable);
setOnCancelListener(cancelListener);
mAlert = new AlertController(context, this, getWindow());
} public static class Builder {
private final AlertController.AlertParams P;
private int mTheme; public Builder(Context context) {
this(context, resolveDialogTheme(context, 0));
} public Builder(Context context, int theme) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, theme)));
mTheme = theme;
} public Builder setMessage(CharSequence message) {
P.mMessage = message;
return this;
} public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
dialog.setOnDismissListener(P.mOnDismissListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
...
}
}

我们可以看到:AlertDialog的Build是一个静态内部类。AlertDialog设置的属性会暂时保存在Build类的成员变量P(AlertController.AlertParams)中。同时,我们注意到我们设置的属性(如setMessage()),它都回返回本身的AlertBuild对象,这样我们就可以不停地调用它设置的方法(流式接口风格)。

如果我们想获得这个AlertDialog。我们就需要调用建造者的create()方法,在create()方法里面它就会构造出一个Dialog实例,并且将我们刚才设置的属性全部赋给AlertDialog,最后返回AlertDialog的实例

三、总结

从上面的UserBuilder和AlertDialog的例子,我们可以做一些总结。Builder设计模式的适用点:

1.产品的属性较多

2.产品本身不可变——Build后,不建议修改产品。

3.产品属性中有部分非必须的属性。

以上三点恰好符合“注重产品创建过程”的Builder核心思想。

参考资料:

http://www.importnew.com/11506.html 建造者模式实践

http://my.oschina.net/weiCloudS/blog/392872?fromerr=AIX2qbD2 在Android中探秘建造者模式

05-11 17:35