Design Pattern ——Builder

1、基礎知識:先前學習建造者模式的時候,老是以這個UML圖做爲學習基礎資料

 

 

 

而後老是要記住四個角色html

  • 產品類:通常是一個較爲複雜的對象,也就是說建立對象的過程比較複雜,通常會有比較多的代碼量。在本類圖中,產品類是一個具體的類,而非抽象類。實際編程中,產品類能夠是由一個抽象類與它的不一樣實現組成,也能夠是由多個抽象類與他們的實現組成。
  • 抽象建造者:引入抽象建造者的目的,是爲了將建造的具體過程交與它的子類來實現。這樣更容易擴展。通常至少會有兩個抽象方法,一個用來建造產品,一個是用來返回產品。
  • 建造者:實現抽象類的全部未實現的方法,具體來講通常是兩項任務:組建產品;返回組建好的產品。
  • 導演類:負責調用適當的建造者來組建產品,導演類通常不與產品類發生依賴關係,與導演類直接交互的是建造者類。通常來講,導演類被用來封裝程序中易變的部分。住四而後老是要記住四個角色

咱們能夠看到,建造者模式相對工廠方法模式,更加註重產品建造過程,我的認爲這纔是Builder的核心思想。編程

 

2、近日看了一些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 }

優勢以下:app

  • User構造方法是私有的,這意味着該類不能在客戶端代碼裏直接實例化。
  • User全部屬性都是final類型的,在構造方法裏面被賦值。只提供了getter方法。
  • builder類使用流式接口風格,讓客戶端代碼閱讀起來更容易(見getUser())。
  • builder類構造方法只接收必須屬性,爲了確保這些屬性在構造方法裏賦值,只有這些屬性被定義成final類型。

另外還有一個例子:

AlertDialogide

 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的實例ui

 

3、總結

從上面的UserBuilder和AlertDialog的例子,咱們能夠作一些總結。Builder設計模式的適用點:this

1.產品的屬性較多spa

2.產品自己不可變——Build後,不建議修改產品。.net

3.產品屬性中有部分非必須的屬性。

 

以上三點剛好符合「注重產品建立過程」的Builder核心思想。

 

 

參考資料:

http://www.importnew.com/11506.html 建造者模式實踐

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

相關文章
相關標籤/搜索