設計模式之五——建造者模式

原文傳送門

1 介紹

建造者模式(Builder)瞭恰,又叫生成器模式巨税。是對象的創(chuàng)建模式适篙。建造者模式可以將產(chǎn)品的內(nèi)部表象與產(chǎn)品的生成過程分割開來昵观。從而可以使一個建造過程生成具有不同的內(nèi)部表象的產(chǎn)品對象碳抄。

1.1 什么是建造者模式

將一個復雜對象的構建與它的表示分離愉老,使得同樣的構建過程可以創(chuàng)建不同的表示。

1.2 解決什么樣的問題

如果我們用了建造者模式剖效,那么用戶就只需指定需要建造的類型就可以得到它們嫉入,而具體的建造過程和細節(jié)就不需要知道了。

由于建造角色的過程比較復雜璧尸,其中還有相互依賴關系咒林,所以我們使用建造者模式將將建造復雜對象的過程和組成對象的部件解耦。這樣既保證了基本屬性全都一致(這里的一致指的是該包含的應該全都包含)也封裝了其中的具體實現(xiàn)細節(jié)爷光。

同時垫竞,在修改某個具體角色的時候我們只需要修改對應的具體角色就可以了,不會影響到其他角色蛀序。

如果需要新增角色欢瞪,只要再增加一個具體建造者,并在該建造者中寫好具體細節(jié)的建造部分代碼就OK了徐裸。

2 原理

  • 參與者
    • Director:導演者遣鼓。擔任這個角色的類調(diào)用具體建造者角色以創(chuàng)建產(chǎn)品對象。一般不與產(chǎn)品類發(fā)生依賴關系重贺。一般來說骑祟,Director被用來封裝程序中易變的部分。
    • Builder:抽象建造者气笙。給 出一個抽象接口次企,以規(guī)范產(chǎn)品對象的各個組成成分的建造。一般而言健民,此接口獨立于應用程序的商業(yè)邏輯抒巢。模式中直接創(chuàng)建產(chǎn)品對象的是 ConcreteBuilder。ConcreteBuilder必須實現(xiàn)這個接口所要求的兩種方法:一種是建造方法(buildPart1和 buildPart2)秉犹,另一種是返還結構方法(retrieveResult)蛉谜。一般來說,產(chǎn)品所包含的零件數(shù)目與建造方法的數(shù)目相符崇堵。換言之型诚,有多少零件,就有多少相應的建造方法鸳劳。
    • ConcreteBuilder:具體建造者狰贯。它們在應用程序調(diào)用下創(chuàng)建產(chǎn)品的實例。這個角色要完成的任務包括:1.實現(xiàn)抽象建造者Builder所聲明的接口赏廓,給出一步一步地完成創(chuàng)建產(chǎn)品實例的操作涵紊。2.在建造過程完成后,提供產(chǎn)品的實例幔摸。
    • Product:產(chǎn)品摸柄。產(chǎn)品便是建造中的復雜對象。一般來說既忆,一個系統(tǒng)中會有多于一個的產(chǎn)品類驱负,而且這些產(chǎn)品類并不一定有共同的接口,而完全可以是不相關聯(lián)的患雇。

導演者角色是與客戶端打交道的角色跃脊。導演者將客戶端創(chuàng)建產(chǎn)品的請求劃分為對各個零件的建造請求,再將這些請求委派給具體建造者角色苛吱。具體建造者角色是做具體建造工作的酪术,但是卻不為客戶端所知。

一般來說翠储,每有一個產(chǎn)品類拼缝,就有一個相應的具體建造者類。這些產(chǎn)品應當有一樣數(shù)目的零件彰亥,而每有一個零件就相應地在所有的建造者角色里有一個建造方法咧七。

2.1 uml圖

  • 類圖


    類圖
  • 時序圖
時序圖

客戶端負責創(chuàng)建導演者和具體建造者對象。然后任斋,客戶端把具體建造者對象交給導演者继阻,導演者操作具體建造者,開始創(chuàng)建產(chǎn)品废酷。當產(chǎn)品完成后瘟檩,建造者把產(chǎn)品返還給客戶端。

把創(chuàng)建具體建造者對象的任務交給客戶端而不是導演者對象澈蟆,是為了將導演者對象與具體建造者對象的耦合變成動態(tài)的墨辛,從而使導演者對象可以操縱數(shù)個具體建造者對象中的任何一個。

2.2 代碼示例

Director代碼示例

public class Director {

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

}

Builder代碼示例

public interface Builder {

    void buildPart1();

    void buildPart2();

    Product retrieveResult();

}

ConcreteBuilder代碼示例

public class ConcreteBuilder implements Builder {

    private Product product = new Product();

    /**
     * 產(chǎn)品零件建造方法1
     */
    @Override
    public void buildPart1() {
        //構建產(chǎn)品的第一個零件
        product.setPart1("編號:9527");
    }

    /**
     * 產(chǎn)品零件建造方法2
     */
    @Override
    public void buildPart2() {
        //構建產(chǎn)品的第二個零件
        product.setPart2("名稱:XXX");

    }

    /**
     * 產(chǎn)品返還方法
     */
    @Override
    public Product retrieveResult() {
        return product;
    }
}

Product代碼示例

public class Product {

    /**
     * 定義一些關于產(chǎn)品的操作
     */
    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;
    }
}

調(diào)用示例

    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());
    }

運行結果

編號:9527
名稱:XXX

2.3 優(yōu)缺點

  • 優(yōu)點
    • 客戶端不必知道產(chǎn)品內(nèi)部組成的細節(jié)奏赘,將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過程解耦,使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品對象太惠。
    • 用戶使用不同的具體建造者即可得到不同的產(chǎn)品對象 磨淌。
    • 可以更加精細地控制產(chǎn)品的創(chuàng)建過程 。
    • 增加新的具體建造者無須修改原有類庫的代碼凿渊,指揮者類針對抽象建造者類編程梁只,系統(tǒng)擴展方便,符合“開閉原則”埃脏。
  • 缺點
    • 建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點搪锣,其組成部分相似,如果產(chǎn)品之間的差異性很大彩掐,則不適合使用建造者模式构舟,因此其使用范圍受到一定的限制。

    • 如果產(chǎn)品的內(nèi)部變化復雜佩谷,可能會導致需要定義很多具體建造者類來實現(xiàn)這種變化旁壮,導致系統(tǒng)變得很龐大。

3 適用場景

在以下情況下可以使用建造者模式:

  1. 需要生成的產(chǎn)品對象有復雜的內(nèi)部結構谐檀,這些產(chǎn)品對象通常包含多個成員屬性抡谐。

  2. 需要生成的產(chǎn)品對象的屬性相互依賴,需要指定其生成順序桐猬。

  3. 對象的創(chuàng)建過程獨立于創(chuàng)建該對象的類麦撵。在建造者模式中引入了指揮者類,將創(chuàng)建過程封裝在指揮者類中溃肪,而不在建造者類中免胃。

  4. 隔離復雜對象的創(chuàng)建和使用,并使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品惫撰。

4 與其他模式的關系

4.1 建造者模式與策略模式的區(qū)別

建造者模式在結構上很接近于策略模式羔沙,事實上建造者模式是策略模式的一種特殊情況。

二者的區(qū)別在于用意不同厨钻。
建造者模式作用于客戶端一點一點的建造新的對象扼雏。不同類型的具體建造者雖然都擁有相同的接口,但是他們所創(chuàng)建出來的對象則可能完全不同夯膀。
而策略模式的目的是為算法提供抽象的接口诗充。一個具體策略類把一個算法包裝到一個對象里面,而不同額具體策略對象為一種一般性的服務提供不同的實現(xiàn)诱建。

4 總結

在建造者模式的結構中引入了一個Director類蝴蜓,該類的作用主要有兩個:一方面它隔離了客戶與生產(chǎn)過程;另一方面它負責控制產(chǎn)品的生成過程。Director針對抽象建造者編程茎匠,客戶端只需要知道具體建造者的類型格仲,即可通過Director類調(diào)用建造者的相關方法,返回一個完整的產(chǎn)品對象汽抚。

建造者模式分成兩個很重要的部分:

1. 一個部分是Builder接口抓狭,這里是定義了如何構建各個部件伯病,也就是知道每個部件功能如何實現(xiàn)造烁,以及如何裝配這些部件到產(chǎn)品中去;

2. 另外一個部分是Director午笛,Director是知道如何組合來構建產(chǎn)品惭蟋,也就是說Director負責整體的構建算法,而且通常是分步驟地來執(zhí)行药磺。

不管如何變化告组,建造模式都存在這么兩個部分,一個部分是部件構造和產(chǎn)品裝配癌佩,另一個部分是整體構建的算法木缝。認識這點是很重要的,因為在建造模式中围辙,強調(diào)的是固定整體構建的算法我碟,而靈活擴展和切換部件的具體構造和產(chǎn)品裝配的方式。

再直白點說姚建,建造模式的重心在于分離構建算法和具體的構造實現(xiàn)矫俺,從而使得構建算法可以重用。具體的構造實現(xiàn)可以很方便地擴展和切換掸冤,從而可以靈活地組合來構造出不同的產(chǎn)品對象厘托。


參考書籍及文章
1.《Java與模式》,電子工業(yè)出版社稿湿,閻宏

  1. 《大話設計模式》铅匹,清華大學出版社,程杰
  2. 《設計模式——可復用面向?qū)ο筌浖幕A》饺藤,機械工業(yè)出版社包斑,Erich Gamma,Richard Helm策精,Ralph Johnson舰始,John Vlissides
  3. 《23種設計模式(4):建造者模式》, https://blog.csdn.net/zhengzhb/article/details/7375966
  4. 《圖說設計模式》咽袜,https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/builder.html
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丸卷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子询刹,更是在濱河造成了極大的恐慌谜嫉,老刑警劉巖萎坷,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沐兰,居然都是意外死亡哆档,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門住闯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓜浸,“玉大人,你說我怎么就攤上這事比原〔宸穑” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵量窘,是天一觀的道長雇寇。 經(jīng)常有香客問我,道長蚌铜,這世上最難降的妖魔是什么锨侯? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮冬殃,結果婚禮上囚痴,老公的妹妹穿的比我還像新娘。我一直安慰自己造壮,他們只是感情好渡讼,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耳璧,像睡著了一般成箫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旨枯,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天蹬昌,我揣著相機與錄音,去河邊找鬼攀隔。 笑死皂贩,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的昆汹。 我是一名探鬼主播明刷,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼满粗!你這毒婦竟也來了辈末?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挤聘,沒想到半個月后轰枝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡组去,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年鞍陨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片从隆。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡诚撵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出广料,到底是詐尸還是另有隱情砾脑,我是刑警寧澤幼驶,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布艾杏,位于F島的核電站,受9級特大地震影響盅藻,放射性物質(zhì)發(fā)生泄漏购桑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一氏淑、第九天 我趴在偏房一處隱蔽的房頂上張望勃蜘。 院中可真熱鬧,春花似錦假残、人聲如沸缭贡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阳惹。三九已至,卻和暖如春眶俩,著一層夾襖步出監(jiān)牢的瞬間莹汤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工颠印, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纲岭,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓线罕,卻偏偏與公主長得像止潮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钞楼,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容