1. 程式人生 > 其它 >建造者設計模式

建造者設計模式

一、建造者模式的概念
建造者模式屬於建立型設計模式。指的是將一個複雜的構建與其表示相分離,使得同樣的構建過程可以建立不同的表示。建造者模式主要解決在軟體系統中,有時候面臨著"一個複雜物件"的建立工作,其通常由各個部分的子物件用一定的演算法構成;由於需求的變化,這個複雜物件的各個部分經常面臨著劇烈的變化,但是將它們組合在一起的演算法卻相對穩定。
建造者模式主要涉及幾個角色:
1、指揮者(Director),負責和客戶(Client)對話
2、之後指揮者將客戶的產品需求劃分為比較穩定的建造過程(AbstractBuilder)
3、指揮者指揮具體的建造者(ConcreteBuilder)幹活
4、獲取建造者建造的產品給客戶


比如組裝電腦這個場景,CPU、主機板、硬碟和記憶體等配件是相對穩定的,組裝過程也是相當穩定的,先裝CPU、記憶體、硬碟和電源等等(AbstractBuilder),但是配件搭配的方式是多變的(Builder可以多個),如組裝家用電腦、遊戲電腦。

二.使用場景:
這個就非常重要了,因為如果你學了個東西,都不知道用來解決什麼問題,你說有什麼用?理解使用場景的的重要性要遠高於你是不是會實現這個模式,因為只要你知道什麼問題可以使用builder模式來解決,那你即使不會寫,也可以在調查相關資料後完成。 我不想說一些大而正確的術語來把你搞蒙,我們只針對具體的問題,至於延展性的思考,隨著你知識的增長,逐漸會明白的。

當一個類的建構函式引數個數超過4個,而且這些引數有些是可選的引數,考慮使用構造者模式。
三.解決的問題:
當一個類的建構函式引數超過4個,而且這些引數有些是可選的時,我們通常有兩種辦法來構建它的物件。 例如我們現在有如下一個類計算機類Computer,其中cpu與ram是必填引數,而其他3個是可選引數,那麼我們如何構造這個類的例項呢,通常有兩種常用的方式:

public class Computer {
    private String cpu;//必須
    private String ram;//必須
    private int usbCount;//可選
    private String keyboard;//
可選 private String display;//可選 }

第一:摺疊建構函式模式(telescoping constructor pattern ),這個我們經常用,如下程式碼所示

public class Computer {
     ...
    public Computer(String cpu, String ram) {
        this(cpu, ram, 0);
    }
    public Computer(String cpu, String ram, int usbCount) {
        this(cpu, ram, usbCount, "羅技鍵盤");
    }
    public Computer(String cpu, String ram, int usbCount, String keyboard) {
        this(cpu, ram, usbCount, keyboard, "三星顯示器");
    }
    public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {
        this.cpu = cpu;
        this.ram = ram;
        this.usbCount = usbCount;
        this.keyboard = keyboard;
        this.display = display;
    }
}

第二種:Javabean 模式,如下所示

public class Computer {
        ...

    public String getCpu() {
        return cpu;
    }
    public void setCpu(String cpu) {
        this.cpu = cpu;
    }
    public String getRam() {
        return ram;
    }
    public void setRam(String ram) {
        this.ram = ram;
    }
    public int getUsbCount() {
        return usbCount;
    }
...
}

那麼這兩種方式有什麼弊端呢?
第一種主要是使用及閱讀不方便。你可以想象一下,當你要呼叫一個類的建構函式時,你首先要決定使用哪一個,然後裡面又是一堆引數,如果這些引數的型別很多又都一樣,你還要搞清楚這些引數的含義,很容易就傳混了。。。那酸爽誰用誰知道。
第二種方式在構建過程中物件的狀態容易發生變化,造成錯誤。因為那個類中的屬性是分步設定的,所以就容易出錯。
為了解決這兩個痛點,builder模式就橫空出世了。
如何實現

  1. 在Computer 中建立一個靜態內部類 Builder,然後將Computer 中的引數都複製到Builder類中。
  2. 在Computer中建立一個private的建構函式,引數為Builder型別
  3. 在Builder中建立一個public的建構函式,引數為Computer中必填的那些引數,cpu 和ram。
  4. 在Builder中建立設定函式,對Computer中那些可選引數進行賦值,返回值為Builder型別的例項
  5. 在Builder中建立一個build()方法,在其中構建Computer的例項並返回

下面程式碼就是最終的樣子

郭慕榮部落格園