Java建造者設(shè)計(jì)模式詳解
建造者模式(Builder):將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。
使用場(chǎng)景:
- 當(dāng)創(chuàng)建復(fù)雜對(duì)象的算法應(yīng)該獨(dú)立于該對(duì)象的組成部分以及它們的裝配方式時(shí)。
- 當(dāng)構(gòu)造過(guò)程必須允許被構(gòu)造的對(duì)象有不同的表示時(shí)。
通用類(lèi)圖:
舉例:我們生活當(dāng)中有許多設(shè)備都是以組裝的形式存在的,例如臺(tái)式電腦,那么有些廠商就會(huì)推出一些具有默認(rèn)配置的組裝電腦主機(jī)(這里可以用到模板方法模式來(lái)實(shí)現(xiàn)),顧客可以購(gòu)買(mǎi)默認(rèn)配置的產(chǎn)品,也可以要求廠商重新組裝一部不同配置不同組裝方式的主機(jī)。此時(shí),我們就可以使用建造者模式來(lái)滿(mǎn)足特殊顧客的要求了。
注意到這個(gè)例子中廠商是重新組裝一部主機(jī),即關(guān)注點(diǎn)是主機(jī)的每個(gè)組成部分,這就符合上面Builder模式給出的使用場(chǎng)景了。
簡(jiǎn)單代碼實(shí)現(xiàn)如下:
//抽象產(chǎn)品類(lèi),使用了模板方法模式,不同產(chǎn)品有不同的“組成部分part” abstract class AbstractProduct{ protected abstract void part01(); protected abstract void part02(); protected abstract void part03(); //模板方法給出了默認(rèn)的組裝方式,生成默認(rèn)的產(chǎn)品 public final AbstractProduct defaultProduct() { part01(); part02(); part03(); return this;//返回當(dāng)前對(duì)象,即默認(rèn)組裝方式的產(chǎn)品 } } //具體的產(chǎn)品A、B,不同產(chǎn)品實(shí)現(xiàn)了不同的“組成部分part” class ConcreteProductA extends AbstractProduct{ protected void part01() { System.out.println("產(chǎn)品A :part01() ..."); } protected void part02() { System.out.println("產(chǎn)品A :part02() ..."); } protected void part03() { System.out.println("產(chǎn)品A :part03() ..."); } } class ConcreteProductB extends AbstractProduct{ protected void part01() { System.out.println("產(chǎn)品B :part01() ..."); } protected void part02() { System.out.println("產(chǎn)品B :part02() ..."); } protected void part03() { System.out.println("產(chǎn)品B :part03() ..."); } } //抽象建造者,制定每一種產(chǎn)品應(yīng)該實(shí)現(xiàn)的組合方式buildPart()和生產(chǎn)buildProduct()的標(biāo)準(zhǔn) abstract class AbstractBuilder{ public abstract void buildPart(); public abstract AbstractProduct buildProduct(); } /* * 具體建造者,如果對(duì)于默認(rèn)產(chǎn)品(即當(dāng)調(diào)用抽象產(chǎn)品中的defaultProduct()方法)不滿(mǎn)意時(shí), * 可以不調(diào)用它來(lái)獲得產(chǎn)品,而是使用具體的建造者來(lái)改變產(chǎn)品的生產(chǎn)組裝方式,以得到不同的產(chǎn)品 */ class ConcreteBuilderA extends AbstractBuilder{ private AbstractProduct productA = new ConcreteProductA(); public void buildPart() { this.productA.part03(); this.productA.part02(); this.productA.part01(); } public AbstractProduct buildProduct() { return this.productA; } } class ConcreteBuilderB extends AbstractBuilder{ private AbstractProduct productB = new ConcreteProductB(); public void buildPart() { this.productB.part02(); this.productB.part01(); //特地省略掉產(chǎn)品B中的一個(gè)組成部分,例如該部分的功能顧客不需要 // this.productB.part03(); } public AbstractProduct buildProduct() { return this.productB; } } //導(dǎo)演類(lèi),預(yù)先持有各個(gè)產(chǎn)品的建造者,為需要不同于默認(rèn)產(chǎn)品的用戶(hù)提供不同的組裝方式 class Director{ private AbstractBuilder builderA = new ConcreteBuilderA(); private AbstractBuilder builderB = new ConcreteBuilderB(); public AbstractProduct getProductA() { this.builderA.buildPart(); return this.builderA.buildProduct(); } public AbstractProduct getProductB() { this.builderB.buildPart(); return this.builderB.buildProduct(); } } //測(cè)試類(lèi) public class Client { public static void main(String[] args) { System.out.println("利用模板方法模式獲得默認(rèn)的產(chǎn)品A"); AbstractProduct defualtProductA = new ConcreteProductA().defaultProduct(); System.out.println("\n利用Director類(lèi)獲得不同組裝方式的產(chǎn)品A"); Director director = new Director(); director.getProductA(); System.out.println("\n利用Director類(lèi)獲得不同組裝方式的產(chǎn)品B"); director.getProductB(); } }
測(cè)試結(jié)果:
利用模板方法模式獲得默認(rèn)的產(chǎn)品A
產(chǎn)品A :part01() ...
產(chǎn)品A :part02() ...
產(chǎn)品A :part03() ...
利用Director類(lèi)獲得不同組裝方式的產(chǎn)品A
產(chǎn)品A :part03() ...
產(chǎn)品A :part02() ...
產(chǎn)品A :part01() ...
利用Director類(lèi)獲得不同組裝方式的產(chǎn)品B
產(chǎn)品B :part02() ...
產(chǎn)品B :part01() ...
其實(shí)在這個(gè)例子當(dāng)中,產(chǎn)品類(lèi)那一部分用到了上一篇文章講到的模板方法模式,即defaultProduct()提供了一個(gè)產(chǎn)品的默認(rèn)組成部分的組裝方式。
但是這里我有個(gè)疑問(wèn),AbstractProduct類(lèi)中根據(jù)模板方法模式提供的的所謂默認(rèn)組裝方式只是打印出幾句測(cè)試的話而已,又不是真正返回一個(gè)具體產(chǎn)品,但是上面例子中那樣返回一個(gè)當(dāng)前對(duì)象(return this;)的處理方式不知道是否合理?
另外,在寫(xiě)了這幾篇關(guān)于用Java代碼實(shí)現(xiàn)設(shè)計(jì)模式的文章之后,發(fā)現(xiàn)這個(gè)建造者Builder模式似乎是結(jié)合了抽象工廠模式、模板方法模式。上面一段已經(jīng)說(shuō)過(guò)我的疑惑,至于抽象工廠模式,我個(gè)人是覺(jué)得上面代碼例子中的Director類(lèi)就很類(lèi)似抽象工廠的具體工廠類(lèi)了,但是Director類(lèi)還要負(fù)責(zé)build一下產(chǎn)品的組裝方式才返回一個(gè)產(chǎn)品,也許就是這個(gè)“build一下”才顯得建造者模式關(guān)注于產(chǎn)品各個(gè)部分的組裝,而抽象工廠模式僅僅只是關(guān)注于一個(gè)最終產(chǎn)品的生成。
之前看過(guò)一句話說(shuō)大概是說(shuō):計(jì)算機(jī)方面的任何一個(gè)問(wèn)題如果難以解決,都可以通過(guò)增加一個(gè)中間層來(lái)處理。現(xiàn)在想了一下,好像Abstract Factory和Builder模式都是運(yùn)用了這一“原理”來(lái)達(dá)到想要的效果。譬如Abstract Factory中有個(gè)抽象工廠類(lèi),Builder中有個(gè)Director類(lèi),說(shuō)到底也就是封裝隱藏某些細(xì)節(jié),并從實(shí)現(xiàn)和使用這兩者之間解耦出來(lái)吧。
我認(rèn)為,一定要先理解了各個(gè)模式的關(guān)注點(diǎn)和適用場(chǎng)景之后才能更好地把握這些吧。
可能這幾個(gè)模式都是創(chuàng)建型的模式而且我沒(méi)有什么實(shí)戰(zhàn)經(jīng)驗(yàn)才會(huì)使得我對(duì)于這些有點(diǎn)混淆了...不怕,在它們?nèi)繉?shí)現(xiàn)的過(guò)程中一點(diǎn)點(diǎn)思考,慢慢地運(yùn)用到實(shí)際當(dāng)中去應(yīng)該就會(huì)逐漸明白的了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所啟發(fā)。
- java設(shè)計(jì)模式系列之裝飾者模式
- 理解java設(shè)計(jì)模式之建造者模式
- 詳解Java設(shè)計(jì)模式編程中的中介者模式
- 深入解析Java的設(shè)計(jì)模式編程中建造者模式的運(yùn)用
- Java設(shè)計(jì)模式編程之工廠方法模式的使用
- Java觀察者設(shè)計(jì)模式詳解
- 理解Java設(shè)計(jì)模式編程中的迪米特原則
- 舉例說(shuō)明Java設(shè)計(jì)模式編程中ISP接口隔離原則的使用
- 簡(jiǎn)單理解遵循接口隔離原則的Java設(shè)計(jì)模式編程
- 實(shí)例講解Java設(shè)計(jì)模式編程中的OCP開(kāi)閉原則
- 簡(jiǎn)單講解Java設(shè)計(jì)模式編程中的單一職責(zé)原則
相關(guān)文章
MyBatis注解方式之@Update/@Delete使用詳解
這篇文章主要介紹了MyBatis注解方式之@Update/@Delete使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11手工體驗(yàn)smtp和pop3協(xié)議 郵件實(shí)現(xiàn)詳解(二)
POP3/IMAP協(xié)議定義了郵件客戶(hù)端軟件和POP3郵件服務(wù)器的通信規(guī)則,這篇文章我們就來(lái)手工體驗(yàn)SMTP和POP3協(xié)議的奧秘,感興趣的小伙伴們可以參考一下2017-10-10java.lang.NullPointerException出現(xiàn)的幾種原因及解決方案
這篇文章主要介紹了java.lang.NullPointerException出現(xiàn)的幾種原因及解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05詳解Java動(dòng)態(tài)字節(jié)碼技術(shù)
Java字節(jié)碼增強(qiáng)指的是在Java字節(jié)碼生成之后,對(duì)其進(jìn)行修改,增強(qiáng)其功能,可減少冗余代碼,提高性能等。本文將詳細(xì)介紹Java動(dòng)態(tài)字節(jié)碼技術(shù)。2021-05-05java基礎(chǔ)教程之拼圖游戲的實(shí)現(xiàn)
拼圖游戲大家應(yīng)該都玩過(guò),下面這篇文章主要給大家介紹了關(guān)于java基礎(chǔ)教程之拼圖游戲的實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-01-01Java?ynchronized重量級(jí)鎖的核心原理詳解
這篇文章主要為大家詳細(xì)介紹了Java?ynchronized重量級(jí)鎖的核心原理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-0329個(gè)要點(diǎn)幫你完成java代碼優(yōu)化
本文給大家分享的是個(gè)人總結(jié)的29個(gè)java優(yōu)化需要注意的地方,非常的全面細(xì)致,推薦給大家,有需要的小伙伴可以參考下2015-03-03