設計模式-3-建造者模式(Builder Pattern)

建造者模式(Builder Pattern) ,將一個複雜對象的構建和它的表示分離,使得一樣的建立過程能夠建立不一樣的表示。在Android 中也是很是的常見的,好比:java

 /**
  * 給寶貝撥打電話
  * 
  * @param no
  */
 private void CallBaby() {
  new AlertDialog.Builder(getActivity())   
  .setTitle(R.string.call_baby)  
  .setMessage(R.string.call_baby_tips)  
  .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface arg0, int arg1) {
    Intent intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+babyListBean.getFullPhone()));  
    startActivity(intent);  
   }
  })  
  .setNegativeButton(R.string.no, null)  
  .show(); 
 }

AlertDialog 的Builder經過setTitle(),setMessage(),setxxButton等方法在create()中構造出一個   AlertDialogInstance對象。而後客戶能夠把把AlertDialogInstance對象show出去。UML 表示以下:web

 

《Effective Java》P9 第二條:遇到多個構造器參數時候要考慮用構造器(爲了對比又要設計工廠方法)數組

使用Builder模式來替代多參數構造函數是一個比較好的實踐法則。ide

 

咱們經常會面臨編寫一個這樣的實現類(假設類名叫MemberContact,是關於會員資料的),這個類擁有多個構造函數,函數

MemberContact(String name,String phone);ui

MemberContact(String name, String phone,int age);this

MemberContact(String name, String phone,int age, String address);spa

MemberContact(String name, String phone,int age, String address, int cardID);設計

MemberContact(String name, String phone,int age, String address, int cardID, type ...);代理

這樣一系列的構造函數主要目的就是爲了提供更多的客戶調用選擇,以處理不一樣的構造請求。這種方法很常見,也頗有效力,可是它的缺點也不少。類的做者不得不書寫多種參數組合的構造函數,並且其中還須要設置默認參數值,這是一個須要細心而又枯燥的工做。

其次,這樣的構造函數靈活性也不高,並且在調用時你不得不提供一些沒有意義的參數值,例如,MemberContact("Anylife","10086" ,-1),顯然年齡爲負數沒有意義,可是你又不的不這樣作,得以符合Java的規範。若是這樣的代碼發佈後,後面的維護者就會很頭痛,由於他根本不知道這個-1是什麼含義。對於這樣的狀況,就很是適合使用Builder模式。Builder模式的要點就是經過一個代理來完成對象的構建過程。這個代理職責就是完成構建的各個步驟,同時它也是易擴展的。下面是改寫自Effective Java裏面的一段代碼:

 

/**
 * 
 * 
 * @author Anylife.zlb@gmail.com
 *
 */
public class MemberContact {
    private final String name;
    private final String phone;   //一個會員的姓名和電話號碼是必填項目
    private final int    age;
    private final int    safeID;
    private final String address;
//  private final type   params...
    /**
     * 私有構造方法,在class Builder 中完成Build 後            
     * return new DoDoContact(Builder instance);
     * 有點代理的感受哈
     * 
     * @param b
     */
    private MemberContact(Builder b) {
        age = b.age;
        safeID = b.safeID;
        name = b.name;
        address = b.address;
        phone = b.phone;
    }
    
    
//    public int getAge() {
//        return age;
//    }
// 
//    public int getSafeID() {
//        return safeID;
//    }
// 
//    public String getName() {
//        return name;
//    }
// 
//    public String getAddress() {
//        return address;
//    }
   
    public static class Builder {
        private String name    = null;
        private String phone = null;
        
        private int    age     = 0;
        private int    safeID  = 0;
        private String address = null;
        public MemberContact build() { // 構建,返回一個新對象
            return new MemberContact(this);
        } 
        
        public Builder(String name,String phone) {
            this.name = name;//這兩個是必填的參數
             this.phone=phone;

        }
        
        public Builder phone(String val) {
         phone = val;
            return this;
        }
 
        public Builder age(int val) {
            age = val;
            return this;
        }
 
        public Builder safeID(int val) {
            safeID = val;
            return this;
        }
 
        public Builder address(String val) {
            address = val;
            return this;
        }
 
    }
}

 

 爲所欲爲的調用:
//    MemberContact mc1 = new MemberContact.Builder("who").phone(110).address("shenzhen").build();

//    MemberContact mc2 = new MemberContact.Builder("anylife").phone(1882656).age(10).address("beijing").build();

相關文章
相關標籤/搜索