Java通俗易懂系列設(shè)計(jì)模式之建造者模式
介紹
今天我們將研究java中的Builder模式。Builder 設(shè)計(jì)模式是一種創(chuàng)造性的設(shè)計(jì)模式,如工廠模式和抽象工廠模式。
當(dāng)Object包含許多屬性時(shí),引入了Builder模式來(lái)解決Factory和Abstract Factory設(shè)計(jì)模式的一些問(wèn)題。
當(dāng)Object包含許多屬性時(shí),F(xiàn)actory和Abstract Factory設(shè)計(jì)模式存在三個(gè)主要問(wèn)題。
- 從客戶端程序傳遞到Factory類的參數(shù)太多,可能容易出錯(cuò),因?yàn)榇蠖鄶?shù)情況下,參數(shù)的類型是相同的,而從客戶端來(lái)說(shuō),很難維護(hù)參數(shù)的順序。
- 一些參數(shù)可能是可選的,但在Factory模式中,我們被迫發(fā)送所有需要發(fā)送為NULL的參數(shù)和可選參數(shù)。
- 如果對(duì)象很重并且它的創(chuàng)建很復(fù)雜,那么所有這些復(fù)雜性都將成為Factory類的一部分,令人困惑。
我們可以通過(guò)提供具有所需參數(shù)的構(gòu)造函數(shù)然后使用不同的setter方法來(lái)設(shè)置可選參數(shù)來(lái)解決大量參數(shù)的問(wèn)題。這種方法的問(wèn)題是,除非明確設(shè)置所有屬性,否則Object狀態(tài)將不一致。
Builder模式通過(guò)提供逐步構(gòu)建對(duì)象的方法并提供實(shí)際返回最終Object的方法,解決了大量可選參數(shù)和不一致?tīng)顟B(tài)的問(wèn)題。
意圖
將復(fù)雜對(duì)象的構(gòu)造與其表示分開(kāi),以便相同的構(gòu)造過(guò)程可以創(chuàng)建不同的表示。
定義
現(xiàn)實(shí)世界的例子:
想象一下角色扮演游戲的角色生成器。最簡(jiǎn)單的選擇是讓計(jì)算機(jī)為您創(chuàng)建角色。但是如果你想選擇職業(yè),性別,頭發(fā)顏色等角色細(xì)節(jié),那么角色生成將成為一個(gè)循序漸進(jìn)的過(guò)程,在所有選擇準(zhǔn)備就緒時(shí)完成。
簡(jiǎn)單來(lái)說(shuō):
允許您創(chuàng)建不同風(fēng)格的對(duì)象,同時(shí)避免構(gòu)造函數(shù)被污染。當(dāng)有幾種不同的構(gòu)造函數(shù)時(shí)很有用?;蛘咴趧?chuàng)建對(duì)象時(shí)涉及很多步驟。
維基百科說(shuō):
構(gòu)建器模式是對(duì)象創(chuàng)建軟件設(shè)計(jì)模式,其目的是找到伸縮構(gòu)造器反模式的解決方案。
話雖如此,讓我補(bǔ)充說(shuō)一下伸縮構(gòu)造器反模式是什么。某時(shí)某刻,我們都會(huì)看到如下構(gòu)造函數(shù):
public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) { }
正如您所看到的,構(gòu)造函數(shù)參數(shù)的數(shù)量很快就會(huì)失控,并且可能很難理解參數(shù)的排列。此外,如果您希望將來(lái)添加更多選項(xiàng),此參數(shù)列表可能會(huì)繼續(xù)增長(zhǎng)。這就被稱為"the telescoping constructor anti-pattern"(可伸縮構(gòu)造器的反模式)。
理智的替代方案是使用Builder模式。
實(shí)例
讓我們看看如何在java中實(shí)現(xiàn)構(gòu)建器設(shè)計(jì)模式。
- 首先,您需要?jiǎng)?chuàng)建一個(gè)靜態(tài)嵌套類,然后將所有參數(shù)從外部類復(fù)制到Builder類。我們應(yīng)該遵循命名約定,如果類名是Computer那么構(gòu)建器類應(yīng)該命名為ComputerBuilder。
- Java Builder類應(yīng)該有一個(gè)公共構(gòu)造函數(shù),其中包含所有必需的屬性作為參數(shù)。
- Java Builder類應(yīng)具有設(shè)置可選參數(shù)的方法,并且應(yīng)在設(shè)置可選屬性后返回相同的Builder對(duì)象。
- 最后一步是build()在構(gòu)建器類中提供一個(gè)方法,該方法將返回客戶端程序所需的Object。為此,我們需要在Class中使用Builder類作為參數(shù)的私有構(gòu)造函數(shù)。
下面是示例構(gòu)建器模式示例代碼,首先,我們有我們想要?jiǎng)?chuàng)造的英雄
public final class Hero { private final Profession profession; private final String name; private final HairType hairType; private final HairColor hairColor; private final Armor armor; private final Weapon weapon; private Hero(Builder builder) { this.profession = builder.profession; this.name = builder.name; this.hairColor = builder.hairColor; this.hairType = builder.hairType; this.weapon = builder.weapon; this.armor = builder.armor; } }
然后我們有了建設(shè)者
public static class HeroBuilder { private final Profession profession; private final String name; private HairType hairType; private HairColor hairColor; private Armor armor; private Weapon weapon; public Builder(Profession profession, String name) { if (profession == null || name == null) { throw new IllegalArgumentException("profession and name can not be null"); } this.profession = profession; this.name = name; } public Builder withHairType(HairType hairType) { this.hairType = hairType; return this; } public Builder withHairColor(HairColor hairColor) { this.hairColor = hairColor; return this; } public Builder withArmor(Armor armor) { this.armor = armor; return this; } public Builder withWeapon(Weapon weapon) { this.weapon = weapon; return this; } public Hero build() { return new Hero(this); } }
請(qǐng)注意,Hero類只有g(shù)etter方法,沒(méi)有公共構(gòu)造函數(shù)。因此,獲取Hero對(duì)象的唯一方法是通過(guò)HeroBuilder類。
然后它可以用作如下,顯示如何使用Builder類來(lái)獲取對(duì)象:
Hero mage = new Hero.HeroBuilder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();
使用場(chǎng)景
使用Builder模式時(shí)
- 用于創(chuàng)建復(fù)雜對(duì)象的算法應(yīng)該獨(dú)立于構(gòu)成對(duì)象的部分以及它們?nèi)绾谓M裝
- 構(gòu)造過(guò)程必須允許對(duì)構(gòu)造的對(duì)象進(jìn)行不同的表示
JDK中的Builder設(shè)計(jì)模式示例
Java類中的一些構(gòu)建器模式示例是;
- java.lang.StringBuilder#append()(未同步)
- java.lang.StringBuffer#append()(synchronized)
總結(jié)
優(yōu)點(diǎn):
- 建造者獨(dú)立,易擴(kuò)展。
- 便于控制細(xì)節(jié)風(fēng)險(xiǎn)。
缺點(diǎn):
- 產(chǎn)品必須有共同點(diǎn),范圍有限制。
- 如內(nèi)部變化復(fù)雜,會(huì)有很多的建造類。
注意事項(xiàng):
與工廠模式的區(qū)別是:建造者模式更加關(guān)注與零件裝配的順序。
以上就是Java通俗易懂系列設(shè)計(jì)模式之建造者模式的詳細(xì)內(nèi)容,更多關(guān)于Java設(shè)計(jì)模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android bdflow數(shù)據(jù)庫(kù)神器的使用
這篇文章主要介紹了Android bdflow數(shù)據(jù)庫(kù)神器的使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03WebClient拋UnsupportedMediaTypeException異常解決
這篇文章主要為大家介紹了WebClient拋UnsupportedMediaTypeException異常的解決方案,文中給大家介紹了六中方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02總結(jié)Java集合類操作優(yōu)化經(jīng)驗(yàn)
本文主要介紹的就是集合框架的使用經(jīng)驗(yàn),告訴大家如何高效、方便地管理對(duì)象,所有代碼基于JDK7,需要的朋友可以參考下2015-08-08從Myeclipse 導(dǎo)入到eclipse中無(wú)法識(shí)別為 web項(xiàng)目 問(wèn)題的解決步驟
這篇文章主要介紹了從Myeclipse 導(dǎo)入到eclipse中無(wú)法識(shí)別為 web項(xiàng)目 問(wèn)題的解決步驟,需要的朋友可以參考下2018-05-05基于java springboot + mybatis實(shí)現(xiàn)電影售票管理系統(tǒng)
這篇文章主要介紹了基于java springboot + mybatis實(shí)現(xiàn)的完整電影售票管理系統(tǒng)基于java springboot + mybatis,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08httpclient 請(qǐng)求http數(shù)據(jù),json轉(zhuǎn)map的實(shí)例
下面小編就為大家?guī)?lái)一篇httpclient 請(qǐng)求http數(shù)據(jù),json轉(zhuǎn)map的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12編程語(yǔ)言榜單Java與Python并列第二!Julia下滑
日新月異的技術(shù)圈,隨著云、大數(shù)據(jù)、人工智能等主流技術(shù)的廣泛應(yīng)用,作為開(kāi)發(fā)利器的編程語(yǔ)言的最新發(fā)展趨勢(shì)也在無(wú)形中發(fā)生了變化,本文主要介紹了java、Python、Julia等語(yǔ)言在Resmonk榜單的排名2021-08-08SpringMVC數(shù)據(jù)輸出相關(guān)知識(shí)總結(jié)
今天帶大家學(xué)習(xí)SpringMVC的相關(guān)知識(shí),文中對(duì)SpringMVC數(shù)據(jù)輸出作了非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下2021-06-06