Java設(shè)計(jì)模式之建造者模式的示例詳解
1 定義
建造者模式(Builder Patten):將一個(gè)復(fù)雜對(duì)象的構(gòu)建與他的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
建造者模式用于一步一步創(chuàng)建一個(gè)復(fù)雜的對(duì)象,他允許用戶只通過指定復(fù)雜對(duì)象的類型和內(nèi)容進(jìn)行構(gòu)建,用戶不需要知道內(nèi)部的具體構(gòu)建細(xì)節(jié)。建造者模式屬于對(duì)象創(chuàng)建型模式,根據(jù)翻譯的不同,建造者模式又可稱為生成器模式。
2 結(jié)構(gòu)與角色
建造者模式包含4個(gè)角色
- Builder:抽象建造者。為創(chuàng)建一個(gè)Product對(duì)象的各個(gè)部件指定的抽象接口。
- ConcreteBuilder:具體建造者。實(shí)現(xiàn)抽象建造者Builder,構(gòu)建和裝配產(chǎn)品的各個(gè)部件。做具體建造工作,但卻不為客戶端所知。
- Product:產(chǎn)品,被構(gòu)建的復(fù)雜對(duì)象。具體建造者創(chuàng)建該產(chǎn)品的內(nèi)部表示并定義它的裝配過程。包含定義組成部件的類,包括將這些部件裝配成最終的產(chǎn)品的接口。
- Director:指揮者。構(gòu)建一個(gè)使用抽象建造者Builder的對(duì)象。它與客戶端打交道,將客戶端創(chuàng)建產(chǎn)品的請(qǐng)求劃分為對(duì)各個(gè)零件的建造請(qǐng)求,再將這些請(qǐng)求委派給ConcreteBuilders。
3 例子
建造樓房的過程中,有專業(yè)人員繪制圖紙,圖紙中講述干什么,工人根據(jù)圖紙去具體實(shí)現(xiàn)要干的事情,包工頭根據(jù)實(shí)際情況去處理圖紙中方法的執(zhí)行,調(diào)配工人以何種順序完成圖紙上的要求。雖然包工頭和圖紙對(duì)建造高樓很有幫助,但是高樓平地起,卻是由工人們一磚一瓦的搭建起來。
以上的這個(gè)例子很形象的講述建造者模式執(zhí)行過程,其中圖紙就對(duì)應(yīng)Builder(提供方法,要干什么),工人就對(duì)應(yīng)ConcreteBuilder(具體去干方法中規(guī)定的事情),包工頭就對(duì)應(yīng)Director(以何種順序干,調(diào)配工人),高樓就對(duì)應(yīng)Product。
3.1 代碼
3.1.1 Builder類
Builder類只提供抽象的方法,類似于圖紙,只是告訴你建造高樓你需要做什么。
// 抽象方法,要做什么:建設(shè)一個(gè)大樓需要做什么 public abstract class Builder { abstract void builderA(); abstract void builderB(); abstract void builderC(); abstract void builderD(); abstract Product getProduct(); }
3.1.2 Worker類
工人是具體實(shí)現(xiàn)Builder提出的需求,比如水泥、鋼筋等等。工人類直接產(chǎn)生產(chǎn)品(new)
package demo01; // 知道了要做什么,就得有人來具體實(shí)現(xiàn) public class Worker extends Builder{ private Product product; public Worker() { product = new Product(); } @Override void builderA() { product.setBuildA("打地基"); System.out.println("打地基"); } @Override void builderB() { product.setBuildB("鋼筋混凝土"); System.out.println("鋼筋混凝土"); } @Override void builderC() { product.setBuildC("蓋房子"); System.out.println("蓋房子"); } @Override void builderD() { product.setBuildD("油漆、粉刷"); System.out.println("油漆、粉刷"); } Product getProduct() { return product; } }
3.1.3 Product類
當(dāng)產(chǎn)品的本身的屬性一一被滿足的時(shí)候,產(chǎn)品才會(huì)產(chǎn)生。
public class Product { private String buildA; private String buildB; private String buildC; private String buildD; public String getBuildA() { return buildA; } public void setBuildA(String buildA) { this.buildA = buildA; } public String getBuildB() { return buildB; } public void setBuildB(String buildB) { this.buildB = buildB; } public String getBuildC() { return buildC; } public void setBuildC(String buildC) { this.buildC = buildC; } public String getBuildD() { return buildD; } public void setBuildD(String buildD) { this.buildD = buildD; } @Override public String toString() { return "Product{" + "buildA='" + buildA + '\'' + ", buildB='" + buildB + '\'' + ", buildC='" + buildC + '\'' + ", buildD='" + buildD + '\'' + '}'; } }
3.1.4 Director類
包工頭,安排工人怎么去做,比如今天下雨,不打水泥了,去抬鋼筋,今天不下雨了,去打地基。
// 指揮的作用是,以什么樣的順序,完成產(chǎn)品的制作 public class Director { public Product getProduct(Builder builder){ builder.builderA(); builder.builderB(); builder.builderC(); builder.builderD(); return builder.getProduct(); } }
3.1.5 Test測(cè)試類
public class Test01 { public static void main(String[] args) { Director director = new Director(); Product product = director.getProduct(new Worker()); System.out.println(product.toString()); } }
指揮者調(diào)整順序可以得到不同的產(chǎn)品,或者不同的效果(雖然這個(gè)沒體現(xiàn)出來)
4 不使用指揮者的例子
去餐廳吃飯,餐廳里一般有默認(rèn)的套餐,或者自己(用戶)點(diǎn)餐,點(diǎn)餐之后,服務(wù)員根據(jù)訂單負(fù)責(zé)將食品端上來,然后你大快朵頤,享受美食帶來的快感…
在這一場(chǎng)景里,就沒有指揮者,指揮權(quán)到達(dá)了用戶的手里。上面3中的場(chǎng)景,指揮權(quán)就不能到用戶手里,你不能讓人家掏錢還得讓人家自己建(除非是老板)。
4.1 Builder類
public abstract class Builder { abstract Builder builderA(String msg); abstract Builder builderB(String msg); abstract Builder builderC(String msg); abstract Builder builderD(String msg); abstract Product getProduct(); }
4.2 Worker類
public class Worker extends Builder { private Product product; public Worker() { product = new Product(); } Builder builderA(String msg) { product.setBuildA(msg); return this; } Builder builderB(String msg) { product.setBuildB(msg); return this; } Builder builderC(String msg) { product.setBuildC(msg); return this; } Builder builderD(String msg) { product.setBuildD(msg); return this; } Product getProduct() { return product; } }
4.3 Product類
public class Product { private String buildA = "炸雞"; private String buildB = "漢堡"; private String buildC = "可樂"; private String buildD = "大蒜"; public String getBuildA() { return buildA; } public void setBuildA(String buildA) { this.buildA = buildA; } public String getBuildB() { return buildB; } public void setBuildB(String buildB) { this.buildB = buildB; } public String getBuildC() { return buildC; } public void setBuildC(String buildC) { this.buildC = buildC; } public String getBuildD() { return buildD; } public void setBuildD(String buildD) { this.buildD = buildD; } @Override public String toString() { return "Product{" + "buildA='" + buildA + '\'' + ", buildB='" + buildB + '\'' + ", buildC='" + buildC + '\'' + ", buildD='" + buildD + '\'' + '}'; } }
4.4 Test類
public class Test { public static void main(String[] args) { Worker worker = new Worker(); System.out.println(worker.builderA("全家桶") .getProduct()); } }
上面的代碼例子中:Worker就相當(dāng)于服務(wù)員,記錄你點(diǎn)了什么菜,并生成賬單(Product里的信息),反饋給用戶產(chǎn)品。
5 適用場(chǎng)景
- 需要生成的產(chǎn)品對(duì)象有復(fù)雜的內(nèi)部結(jié)構(gòu)(通常包含多個(gè)成員屬性)
- 需要生成的產(chǎn)品對(duì)象的屬性相互依賴(需要指定順序)
- 產(chǎn)品對(duì)象的創(chuàng)建過程獨(dú)立于創(chuàng)建該對(duì)象的類
- 隔離復(fù)雜對(duì)象的創(chuàng)建和使用,并使得相同的創(chuàng)建過程可以創(chuàng)建不同的類
6 優(yōu)缺點(diǎn)
6.1 優(yōu)點(diǎn)
- 用戶不需要知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過程解耦,使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品對(duì)象。
- 很方便的替換具體的建造者或者增加新的具體創(chuàng)建者
- 符合開閉原則,可以更加精細(xì)的控制產(chǎn)品的創(chuàng)建過程
6.2 缺點(diǎn)
- 適用范圍收到限制,需要生成的產(chǎn)品對(duì)象具有較多共同點(diǎn)
- 如果產(chǎn)品的內(nèi)部變化復(fù)雜,可能會(huì)導(dǎo)致需要定義很多具體建造者類來實(shí)現(xiàn)這種變化。
到此這篇關(guān)于Java設(shè)計(jì)模式之建造者模式的示例詳解的文章就介紹到這了,更多相關(guān)Java建造者模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot中集成各種日志框架Logback、Log4j2和Java Util
這篇文章主要介紹了Spring Boot中集成各種日志框架Logback、Log4j2和Java Util Logging,通過實(shí)例代碼介紹了集成Logback、Log4j2和Java Util Logging的基本步驟,你可以根據(jù)自己的需求進(jìn)行配置和擴(kuò)展,以滿足更復(fù)雜的日志需求,需要的朋友可以參考下2023-11-11SpringBoot3整合mybatis-plus的實(shí)現(xiàn)
MyBatis-Plus是一個(gè)MyBatis的增強(qiáng)工具,在MyBatis的基礎(chǔ)上只做增強(qiáng)不做改變,本文主要介紹了Mybatis-Plus3.x的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10Java的Struts框架中的if/else標(biāo)簽使用詳解
這篇文章主要介紹了Java的Struts框架中的if/else標(biāo)簽使用詳解,Struts是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2015-12-12Java BigDecimal使用及基本運(yùn)算(推薦)
Java在java.math包中提供的API類BigDecimal,用來對(duì)超過16位有效位的數(shù)進(jìn)行精確的運(yùn)算。這篇文章主要介紹了Java BigDecimal使用指南針(推薦),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08Java自學(xué)書籍推薦 程序員到架構(gòu)師必看的書
這篇文章主要為大家推薦了Java程序員到架構(gòu)師自學(xué)書籍,幫助大家不斷提高自己的專業(yè)水平,感興趣的小伙伴們可以參考一下2016-09-09IDEA?+?Maven環(huán)境下的SSM框架整合及搭建過程
這篇文章主要介紹了IDEA?+?Maven環(huán)境下的SSM框架整合及搭建過程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01Spring session實(shí)現(xiàn)Session共享
本文主要介紹了Spring session實(shí)現(xiàn)Session共享,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04