Java設(shè)計(jì)模式之建造者模式淺析示例
編程是一門藝術(shù),大批量的改動(dòng)顯然是非常丑陋的做法,用心的琢磨寫的代碼讓它變的更美觀。
1.建造者(Builder)設(shè)計(jì)模式定義
建造者設(shè)計(jì)模式是指將一個(gè)復(fù)雜對(duì)象的構(gòu)造與它的表示分離,使同樣的構(gòu)建過程可以創(chuàng)建不同的表示,這樣的被稱為建造者模式。
它是將一個(gè)復(fù)雜的對(duì)象分解為多個(gè)簡(jiǎn)單的對(duì)象,然后一步一步構(gòu)建而成。它將變與不變相分離,即產(chǎn)品的組成部分是不變的,但每一部分是可以靈活選擇的。
2.建造者設(shè)計(jì)模式優(yōu)點(diǎn)
- 封裝性好,構(gòu)建和表示分離。
- 擴(kuò)展性好,各個(gè)具體的建造者相互獨(dú)立,有利于系統(tǒng)的解耦。
- 客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),建造者可以對(duì)創(chuàng)建過程逐步細(xì)化,而不對(duì)其它模塊產(chǎn)生任何影響,便于控制細(xì)節(jié)風(fēng)險(xiǎn)。
3.建造者設(shè)計(jì)模式不足之處
- 產(chǎn)品的組成部分必須相同,這限制了其使用范圍。
- 如果產(chǎn)品的內(nèi)部變化復(fù)雜,如果產(chǎn)品內(nèi)部發(fā)生變化,則建造者也要同步修改,后期維護(hù)成本較大。
4.建造者設(shè)計(jì)模式角色關(guān)系
建造者(Builder)模式由產(chǎn)品、抽象建造者、具體建造者、指揮者等 4 個(gè)要素構(gòu)成。
- 產(chǎn)品角色(Product):它是包含多個(gè)組成部件的復(fù)雜對(duì)象,由具體建造者來(lái)創(chuàng)建其各個(gè)零部件。
- 抽象建造者(Builder):它是一個(gè)包含創(chuàng)建產(chǎn)品各個(gè)子部件的抽象方法的接口,通常還包含一個(gè)返回復(fù)雜產(chǎn)品的方法 getResult()。
- 具體建造者(Concrete Builder):實(shí)現(xiàn) Builder 接口,完成復(fù)雜產(chǎn)品的各個(gè)部件的具體創(chuàng)建方法。
- 指揮者(Director):它調(diào)用建造者對(duì)象中的部件構(gòu)造與裝配方法完成復(fù)雜對(duì)象的創(chuàng)建,在指揮者中不涉及具體產(chǎn)品的信息。
5.建造者設(shè)計(jì)模式應(yīng)用
建造者設(shè)計(jì)模式應(yīng)用非常廣泛,比如Retrofit、AlertDialog等都使用了建造者設(shè)計(jì)模式。
下面使用Retrofit刪減版本當(dāng)作示例(這是一個(gè)開源項(xiàng)目的真實(shí)場(chǎng)景,更加貼近真實(shí)的應(yīng)用)
public final class Retrofit { Retrofit( okhttp3.Call.Factory callFactory, HttpUrl baseUrl, List<Converter.Factory> converterFactories, int defaultConverterFactoriesSize, List<CallAdapter.Factory> callAdapterFactories, int defaultCallAdapterFactoriesSize, @Nullable Executor callbackExecutor, boolean validateEagerly) { this.callFactory = callFactory; this.baseUrl = baseUrl; this.converterFactories = converterFactories; this.defaultConverterFactoriesSize = defaultConverterFactoriesSize; this.callAdapterFactories = callAdapterFactories; this.defaultCallAdapterFactoriesSize = defaultCallAdapterFactoriesSize; this.callbackExecutor = callbackExecutor; this.validateEagerly = validateEagerly; } public static final class Builder { public Builder() {} public Builder baseUrl(URL baseUrl) { Objects.requireNonNull(baseUrl, "baseUrl == null"); return baseUrl(HttpUrl.get(baseUrl.toString())); } public Builder addCallAdapterFactory(CallAdapter.Factory factory) { callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null")); return this; } public Builder addConverterFactory(Converter.Factory factory) { converterFactories.add(Objects.requireNonNull(factory, "factory == null")); return this; } public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } Platform platform = Platform.get(); okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this.converterFactories); converterFactories.addAll(defaultConverterFactories); return new Retrofit( baseUrl, unmodifiableList(converterFactories), defaultConverterFactoriesSize, unmodifiableList(callAdapterFactories), defaultCallAdapterFactories.size(), callbackExecutor, validateEagerly); } } } } //Retrofit 對(duì)象的創(chuàng)建 Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build();
Retrifit官網(wǎng)地址:https://github.com/square/retrofit
以上內(nèi)容做了刪減,只為說(shuō)明建造者設(shè)計(jì)模式,以上例子中產(chǎn)品角色就是Retrofit,這里Builder就是具體的建造者,當(dāng)用戶使用的時(shí)候,只需要通過建造者設(shè)置具體屬性,比如URL、ConverterFactory等,然后調(diào)用build方法就可以創(chuàng)建Retrofit對(duì)象。
在案例中可以看到,除了URL是必須要添加的之外,其他的都是有默認(rèn)值的,如果不設(shè)置也沒有問題。這樣就可以通過設(shè)置不同的參數(shù),創(chuàng)建出各種各樣的Retrofit對(duì)象了,靈活方便。
建造者模式在應(yīng)用過程中可以根據(jù)需要改變,如果創(chuàng)建的產(chǎn)品種類只有一種,只需要一個(gè)具體建造者,這時(shí)可以省略掉抽象建造者,甚至可以省略掉指揮者角色。以上就是這樣的案例。
6.建造者設(shè)計(jì)模式的應(yīng)用場(chǎng)景
建造者模式唯一區(qū)別于工廠模式的是針對(duì)復(fù)雜對(duì)象的創(chuàng)建。也就是說(shuō),如果創(chuàng)建簡(jiǎn)單對(duì)象,通常都是使用工廠模式進(jìn)行創(chuàng)建,而如果創(chuàng)建復(fù)雜對(duì)象,就可以考慮使用建造者模式。
當(dāng)需要?jiǎng)?chuàng)建的產(chǎn)品具備復(fù)雜創(chuàng)建過程時(shí),可以抽取出共性創(chuàng)建過程,然后交由具體實(shí)現(xiàn)類自定義創(chuàng)建流程,使得同樣的創(chuàng)建行為可以生產(chǎn)出不同的產(chǎn)品,分離了創(chuàng)建與表示,使創(chuàng)建產(chǎn)品的靈活性大大增加。
建造者模式主要適用于以下應(yīng)用場(chǎng)景:
- 相同的方法,不同的執(zhí)行順序,產(chǎn)生不同的結(jié)果。
- 多個(gè)部件或零件,都可以裝配到一個(gè)對(duì)象中,但是產(chǎn)生的結(jié)果又不相同。
- 產(chǎn)品類非常復(fù)雜,或者產(chǎn)品類中不同的調(diào)用順序產(chǎn)生不同的作用。
- 初始化一個(gè)對(duì)象特別復(fù)雜,參數(shù)多,而且很多參數(shù)都具有默認(rèn)值。
到此這篇關(guān)于Java設(shè)計(jì)模式之建造者模式淺析示例的文章就介紹到這了,更多相關(guān)Java建造者模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用@RequestBody配合@Valid校驗(yàn)入?yún)?shù)
這篇文章主要介紹了使用@RequestBody配合@Valid校驗(yàn)入?yún)?shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03將SpringBoot的Jar注冊(cè)成Windows服務(wù)的實(shí)現(xiàn)方法
當(dāng)前項(xiàng)目有個(gè)地圖編輯器,后端用的是SpringBoot框架,外網(wǎng)剛好有一臺(tái)空閑的Windows服務(wù)器就直接拿來(lái)用了,將Java程序部署成Windows服務(wù)可以用WinSW (Windows Service Wrapper)來(lái)實(shí)現(xiàn),文中有詳細(xì)的操作步驟,需要的朋友可以參考下2023-11-11關(guān)于mybatis3中@SelectProvider的使用問題
這篇文章主要介紹了mybatis3中@SelectProvider的使用技巧,@SelectProvide指定一個(gè)Class及其方法,并且通過調(diào)用Class上的這個(gè)方法來(lái)獲得sql語(yǔ)句,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-12-12Java?Spring框架創(chuàng)建項(xiàng)目與Bean的存儲(chǔ)與讀取詳解
本篇文章將介紹Spring項(xiàng)目的創(chuàng)建,IDEA國(guó)內(nèi)源的配置以及Bean的存儲(chǔ)與讀取,所謂的Bean其實(shí)就是對(duì)象的意思,更詳細(xì)地說(shuō)Spring Bean是被實(shí)例的,組裝的及被Spring 容器管理的Java對(duì)象2022-07-07用Maven打成可執(zhí)行jar,包含maven依賴,本地依賴的操作
這篇文章主要介紹了用Maven打成可執(zhí)行jar,包含maven依賴,本地依賴的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-08-08Java實(shí)現(xiàn)實(shí)時(shí)監(jiān)控目錄下文件變化的方法
今天小編就為大家分享一篇關(guān)于Java實(shí)現(xiàn)實(shí)時(shí)監(jiān)控目錄下文件變化的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03