Design Pattern ——Builder


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

 

 

 

然后总是要记住四个角色

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

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

 

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

例子1.

 1 public class User {
2 private final String firstName; // required
3 private final String lastName; // required
4 private final int age; // optional
5 private final String phone; // optional
6 private final String address; // optional
7
8 private User(UserBuilder builder) {
9 this.firstName = builder.firstName;
10 this.lastName = builder.lastName;
11 this.age = builder.age;
12 this.phone = builder.phone;
13 this.address = builder.address;
14 }
15
16 public String getFirstName() {
17 return firstName;
18 }
19
20 public String getLastName() {
21 return lastName;
22 }
23
24 public int getAge() {
25 return age;
26 }
27
28 public String getPhone() {
29 return phone;
30 }
31
32 public String getAddress() {
33 return address;
34 }
35
36 public static class UserBuilder {
37 private final String firstName;
38 private final String lastName;
39 private int age;
40 private String phone;
41 private String address;
42
43 public UserBuilder(String firstName, String lastName) {
44 this.firstName = firstName;
45 this.lastName = lastName;
46 }
47
48 public UserBuilder age(int age) {
49 this.age = age;
50 return this;
51 }
52
53 public UserBuilder phone(String phone) {
54 this.phone = phone;
55 return this;
56 }
57
58 public UserBuilder address(String address) {
59 this.address = address;
60 return this;
61 }
62
63 public User build() {
64 return new User(this);
65 }
66
67 }
68 }

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

1 public User getUser() {
2 return new
3 User.UserBuilder('Jhon', 'Doe')
4 .age(30)
5 .phone('1234567')
6 .address('Fake address 1234')
7 .build();
8 }

优点如下:

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

另外还有一个例子:

AlertDialog

 1 public class AlertDialog extends Dialog implements DialogInterface {
2
3 ...
4
5 protected AlertDialog(Context context, int theme) {
6 this(context, theme, true);
7 }
8
9 AlertDialog(Context context, int theme, boolean createThemeContextWrapper) {
10 super(context, resolveDialogTheme(context, theme), createThemeContextWrapper);
11
12 mWindow.alwaysReadCloseOnTouchAttr();
13 mAlert = new AlertController(getContext(), this, getWindow());
14 }
15
16 protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
17 super(context, resolveDialogTheme(context, 0));
18 mWindow.alwaysReadCloseOnTouchAttr();
19 setCancelable(cancelable);
20 setOnCancelListener(cancelListener);
21 mAlert = new AlertController(context, this, getWindow());
22 }
23
24 public static class Builder {
25 private final AlertController.AlertParams P;
26 private int mTheme;
27
28
29 public Builder(Context context) {
30 this(context, resolveDialogTheme(context, 0));
31 }
32
33
34 public Builder(Context context, int theme) {
35 P = new AlertController.AlertParams(new ContextThemeWrapper(
36 context, resolveDialogTheme(context, theme)));
37 mTheme = theme;
38 }
39
40
41 public Builder setMessage(CharSequence message) {
42 P.mMessage = message;
43 return this;
44 }
45
46 public AlertDialog create() {
47 final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
48 P.apply(dialog.mAlert);
49 dialog.setCancelable(P.mCancelable);
50 if (P.mCancelable) {
51 dialog.setCanceledOnTouchOutside(true);
52 }
53 dialog.setOnCancelListener(P.mOnCancelListener);
54 dialog.setOnDismissListener(P.mOnDismissListener);
55 if (P.mOnKeyListener != null) {
56 dialog.setOnKeyListener(P.mOnKeyListener);
57 }
58 return dialog;
59 }
60 ...
61 }
62 }

我们可以看到: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中探秘建造者模式

 

本站声明
本文转载自:http://www.cnblogs.com/xerrard/p/5021891.html     作者:xerrard     发布日期:2015/12/03     本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。


 
© 2014-2017 ITdaan.com 粤ICP备14056181号