創建型模式之建造者模式(Builder模式)


在軟件開發過程中有時需要創建一個複雜的對象,這個複雜對象通常由多個子部件按一定的步驟組合而成。例如,計算機是由 OPU、主板、內存、硬盤、顯卡、機箱、顯示器、鍵盤、鼠標等部件組裝而成的,採購員不可能自己去組裝計算機,而是將計算機的配置要求告訴計算機銷售公司,計算機銷售公司安排技術人員去組裝計算機,然後再交給要買計算機的採購員。

生活中這樣的例子很多,如遊戲中的不同角色,其性別、個性、能力、臉型、體型、服裝、髮型等特性都有所差異;還有汽車中的方向盤、發動機、車架、輪胎等部件也多種多樣;每封電子郵件的發件人、收件人、主題、內容、附件等內容也各不相同。

以上所有這些產品都是由多個部件構成的,各個部件可以靈活選擇,但其創建步驟都大同小異。這類產品的創建無法用前面介紹的工廠模式描述,只有建造者模式可以很好地描述該類產品的創建。

建造者模式的定義與特點

建造者(Builder)模式的定義:
指將一個複雜對象的構造與它的表示分離,使同樣的構建過程可以創建不同的表示,這樣的設計模式被稱爲建造者模式。它是將一個複雜的對象分解爲多個簡單的對象,然後一步一步構建而成。它將變與不變相分離,即產品的組成部分是不變的,但每一部分是可以靈活選擇的。

該模式的主要優點如下:
1.各個具體的建造者相互獨立,有利於系統的擴展。
2.客戶端不必知道產品內部組成的細節,便於控制細節風險。

其缺點如下:
1.產品的組成部分必須相同,這限制了其使用範圍。
2.如果產品的內部變化複雜,該模式會增加很多的建造者類。

建造者模式的結構

建造者(Builder)模式由產品抽象建造者具體建造者指揮者等 4 個要素構成,如下:
1.產品角色(Product):它是包含多個組成部件的複雜對象,由具體建造者來創建其各個部件。
2.抽象建造者(Builder):它是一個包含創建產品各個子部件的抽象方法的接口,通常還包含一個返回複雜產品的方法 。
3.具體建造者(Concrete Builder):實現 Builder 接口,完成複雜產品的各個部件的具體創建方法。
4.指揮者(Director):它調用建造者對象中的部件構造與裝配方法完成複雜對象的創建,在指揮者中不涉及具體產品的信息。

建造者模式的實現

用建造者(Builder)模式描述手機:

對照上邊抽象工廠模式的結構:

1.產品角色(Phone ):包含多個組成部件的複雜對象

/**
 * 產品:手機
 * 使用lombok插件省去get,set,toString。
 */
@Date
public class Phone {
    private String screen;//屏幕
    private String shell;//外殼
    private String cpu;//處理器
    
}

2.抽象建造者(AbstractWorker ):包含創建產品各個子部件的抽象方法的接口

/**
 * 抽象建造者:造手機的工人
 */
public interface AbstractWorker {
    AbstractWorker buildScreen();//造屏幕
    AbstractWorker buildShell();//造外殼
    AbstractWorker buildCpu();//造處理器
    Phone build();//組裝產品
}

3.具體建造者:實現 AbstractWorker 接口

/**
 * 具體建造者:造華爲手機的工人
 */
public class HWWorker implements AbstractWorker {
    private Phone hwPhone = new Phone();
    
    public AbstractWorker buildScreen() {
        hwPhone.setScreen("華爲的屏幕");
        return this;
    }
    public AbstractWorker buildShell() {
        hwPhone.setShell("華爲的外殼");
        return this;
    }
    public AbstractWorker buildCpu() {
        hwPhone.setCpu("華爲的cpu");
        return this;
    }
    public Phone build() {
        return hwPhone;
    }
}
/**
 * 具體建造者:造小米手機的工人
 */
public class XMWorker implements AbstractWorker{
    private Phone xmPhone = new Phone();
    
    public AbstractWorker buildScreen() {
        xmPhone.setScreen("小米的屏幕");
        return this;
    }
    public AbstractWorker buildShell() {
        xmPhone.setShell("小米的外殼");
        return this;
    }
    public AbstractWorker buildCpu() {
        xmPhone.setCpu("小米的cpu");
        return this;
    }
    public Phone build() {
        return xmPhone;
    }
}

4.指揮者(Director):調用建造者對象中的部件構造與裝配方法完成複雜對象的創建

/**
 * 指揮者
 */
public class Director {
    private AbstractWorker builder;
    //構造方法:給我華爲的工人就構造一個華爲的指揮者
    public Director(AbstractWorker builder) {
        this.builder = builder;
    }
    //產品構建與組裝方法:指揮工人幹活
    public Phone builder(){
        return builder.buildScreen()
                .buildShell()
                .buildCpu()
                .build();
    }
}

5.測試類:

public class BuilderPatternTest {
    @Test
    public void test(){
        showPhone(new HWWorker());
        showPhone(new XMWorker());
    }
    private void showPhone(AbstractWorker builder){
        Director director = new Director(builder);//根據傳入的工人構建不同的指揮者
        Phone phone = director.builder();//指揮工人幹活:造手機
        System.out.println(phone);
    }
}

6.測試結果:
華爲的工人造華爲的手機,小米的工人造小米手機
在這裏插入圖片描述
類結構圖:
在這裏插入圖片描述

應用場景

建造者(Builder)模式創建的是複雜對象,其產品的各個部分經常面臨着劇烈的變化,但將它們組合在一起的算法卻相對穩定,所以它通常在以下場合使用:
1.創建的對象較複雜,由多個部件構成,各部件面臨着複雜的變化,但構件間的建造順序是穩定的。
2.創建複雜對象的算法獨立於該對象的組成部分以及它們的裝配方式,即產品的構建過程和最終的表示是獨立的。

建造者模式和工廠模式的區別

1.建造者模式更加註重方法的調用順序,工廠模式注重創建對象。
2.創建對象的力度不同,建造者模式創建複雜的對象,由各種複雜的部件組成,工廠模式創建出來的都一樣。
3.關注的重點不同,工廠模式只需要把對象創建出來,而建造者不僅要創建出來,還要知道這個對象由哪些部件組成。
4.建造者模式根據建造過程中的順序不一樣,最終的對象部件組成也不一樣。

建造者模式的擴展

建造者(Builder)模式在應用過程中可以根據需要改變,如果創建的產品種類只有一種,只需要一個具體建造者,這時可以省略掉抽象建造者,甚至可以省略掉指揮者角色。比如:

/**
 * 產品:電腦
 */
public class Computer {
    private String screen;//屏幕
    private String shell;//外殼
    private String cpu;//處理器

/**
 * 造電腦的工人
 */
public class Worker {
    private Computer computer = new Computer();
    public Worker buildScreen(String screen) {
        computer.setScreen(screen);
        return this;
    }
    public Worker buildShell(String shell) {
        computer.setShell(shell);
        return this;
    }
    public Worker buildCpu(String cpu) {
        computer.setCpu(cpu);
        return this;
    }
    public Computer build() {
        return computer;
    }
}
	//測試代碼
    @Test
    public void test2 (){
        Computer computer = new Worker().buildScreen("4K屏幕")
                .buildShell("堅硬的外殼")
                .buildCpu("高端處理器")
                .build();
        System.out.println(computer);
    }

運行結果:
在這裏插入圖片描述
上面的示例代碼只是傳入三個參數,如果構造這個對象要13個參數呢,更多的參數呢,builder 模式的優勢將會更加明顯,傳遞參數更加靈活,代碼具有更高的可讀性。

<<上一篇:抽象工廠模式
>>下一篇:代理模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章