Builder模式

定義

建造模式是對象的創建模式。建造模式可以將一個產品的內部表象(internal representation)與產品的生產過程分割開來,從而可以使一個建造過程生成具有不同的內部表象的產品對象。

理解

一個複雜對象的表示應該與它的構建過程分離,使得同樣的構造過程有着不同的表示。

一些概念

產品的內部表象

  一個產品常有不同的組成成分作爲產品的零件,這些零件有可能是對象,也有可能不是對象,它們通常又叫做產品的內部表象(internal representation)。不同的產品可以有不同的內部表象,也就是不同的零件。使用建造模式可以使客戶端不需要知道所生成的產品有哪些零件,每個產品的對應零件彼此有何不同,是怎麼建造出來的,以及怎麼組成產品。

對象性質的建造

  有些情況下,一個對象會有一些重要的性質,在它們沒有恰當的值之前,對象不能作爲一個完整的產品使用。比如,一個電子郵件有發件人地址、收件人地址、主題、內容、附錄等部分,而在最起碼的收件人地址得到賦值之前,這個電子郵件不能發送。
  有些情況下,一個對象的一些性質必須按照某個順序賦值纔有意義。在某個性質沒有賦值之前,另一個性質則無法賦值。這些情況使得性質本身的建造涉及到複雜的商業邏輯。這時候,此對象相當於一個有待建造的產品,而對象的這些性質相當於產品的零件,建造產品的過程是建造零件的過程。由於建造零件的過程很複雜,因此,這些零件的建造過程往往被“外部化”到另一個稱做建造者的對象裏,建造者對象返還給客戶端的是一個全部零件都建造完畢的產品對象。


    建造模式利用一個導演者對象和具體建造者對象一個個地建造出所有的零件,從而建造出完整的產品對象。建造者模式將產品的結構和產品的零件的建造過程對客戶端隱藏起來,把對建造過程進行指揮的責任和具體建造者零件的責任分割開來,達到責任劃分和封裝的目的。

角色

    抽象建造者(Builder)角色:給出一個抽象接口,以規範產品對象的各個組成成分的建造。具體建造者類必須實現這個接口所要求的兩種方法:一種是建造方法(buildPart1和 buildPart2),另一種是返還結構方法(retrieveResult)。一般來說,產品所包含的零件數目與建造方法的數目相符。換言之,有多少 零件,就有多少相應的建造方法。
  具體建造者(ConcreteBuilder)角色:擔任這個角色的是與應用程序緊密相關的一些類,它們在應用程序調用下創建產品的實例。這個角色要完成的任務包括:1.實現抽象建造者Builder所聲明的接口,給出一步一步地完成創建產品實例的操作。2.在建造過程完成後,提供產品的實例。
  導演者(Director)角色:擔任這個角色的類調用具體建造者角色以創建產品對象。應當指出的是,導演者角色並沒有產品類的具體知識,真正擁有產品類的具體知識的是具體建造者角色。
  產品(Product)角色:產品便是建造中的複雜對象。一般來說,一個系統中會有多於一個的產品類,而且這些產品類並不一定有共同的接口,而完全可以是不相關聯的。

UML類圖

Java實現

產品product

public class Product {
    /**
     * 定義一些關於產品的操作
     */
    private String part1;
    private String part2;
    public String getPart1() {
        return part1;
    }
    public void setPart1(String part1) {
        this.part1 = part1;
    }
    public String getPart2() {
        return part2;
    }
    public void setPart2(String part2) {
        this.part2 = part2;
    }
}

抽象建造者

public interface Builder {
    public void buildPart1();
    public void buildPart2();
    public Product retrieveResult();
}

具體建造者

public class ConcreteBuilder implements Builder {
    private Product product = new Product();
    /**
     * 產品零件建造方法1
     */
    @Override
    public void buildPart1() {
        //構建產品的第一個零件
     product.setPart1("編號:9527");
    }
    /**
     * 產品零件建造方法2
     */
    @Override
    public void buildPart2() {
        //構建產品的第二個零件
     product.setPart2("名稱:XXX");
    }
    /**
     * 產品返還方法
     */
    @Override
    public Product retrieveResult() {
        return product;
    }
}

導演類

public class Director {
    /**
     * 持有當前需要使用的建造器對象
     */
    private Builder builder;
    /**
     * 構造方法,傳入建造器對象
     * @param builder 建造器對象
     */
    public Director(Builder builder){
        this.builder = builder;
    }
    /**
     * 產品構造方法,負責調用各個零件建造方法
     */
    public void construct(){
        builder.buildPart1();
        builder.buildPart2();
    }
}

客戶端測試

public class Client {
    public static void main(String[]args){
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.construct();
        Product product = builder.retrieveResult();
        System.out.println(product.getPart1());
        System.out.println(product.getPart2());
    }
}
    以上是標準的Builder模式,在開發過程中演化出一種簡單的Builder模式,那就是沒有導演的角色,客戶端直接調用builder的build方法來來建造對象,如Android的dialog,如下:
//創建build
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
//向build中set各種建造dialog的"原材料",在代碼結構中,這些原材料都是build自帶的,但在實際開發中,經常需要傳入一些對象來創造不同的產品
builder.setTitle('simple dialog').setIcon(R.drawable.tools).setPositiveButton(builder);
//調用create方法創建對話框
AlertDialog dialog = builder.create();
//顯示對話框
dialog.show();
//以上代碼可簡化爲如下形式,在實際開發中我們經常這麼用
new AlertDialog.Builder(mContext)..setTitle('simple dialog').setIcon(R.drawable.tools).setPositiveButton(builder).create().show();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章