深入理解Java設(shè)計(jì)模式之建造者模式
一、什么是建造者模式
建造者模式也稱生成器模式 定義:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示(依賴倒轉(zhuǎn))

產(chǎn)品類(lèi):一般是一個(gè)較為復(fù)雜的對(duì)象,也就是說(shuō)創(chuàng)建對(duì)象的過(guò)程比較復(fù)雜,一般會(huì)有比較多的代碼量。在本類(lèi)圖中,產(chǎn)品類(lèi)是一個(gè)具體的類(lèi),而非抽象類(lèi)。實(shí)際編程中,產(chǎn)品類(lèi)可以是由一個(gè)抽象類(lèi)與它的不同實(shí)現(xiàn)組成,也可以是由多個(gè)抽象類(lèi)與他們的實(shí)現(xiàn)組成。
抽象建造者:引入抽象建造者的目的,是為了將建造的具體過(guò)程交與它的子類(lèi)來(lái)實(shí)現(xiàn)。這樣更容易擴(kuò)展。一般至少會(huì)有兩個(gè)抽象方法,一個(gè)用來(lái)建造產(chǎn)品,一個(gè)是用來(lái)返回產(chǎn)品。
建造者:實(shí)現(xiàn)抽象類(lèi)的所有未實(shí)現(xiàn)的方法,具體來(lái)說(shuō)一般是兩項(xiàng)任務(wù):組建產(chǎn)品;返回組建好的產(chǎn)品。
指揮類(lèi):負(fù)責(zé)調(diào)用適當(dāng)?shù)慕ㄔ煺邅?lái)組建產(chǎn)品,指揮類(lèi)一般不與產(chǎn)品類(lèi)發(fā)生依賴關(guān)系,與指揮類(lèi)直接交互的是建造者類(lèi)。一般來(lái)說(shuō),指揮類(lèi)被用來(lái)封裝程序中易變的部分。
二、建造者模式的應(yīng)用場(chǎng)景
1.創(chuàng)建復(fù)雜對(duì)象的算法獨(dú)立于組成對(duì)象的部件
2.同一個(gè)創(chuàng)建過(guò)程需要有不同的內(nèi)部表象的產(chǎn)品對(duì)象
例子:建房子,不管建什么房子,它們都離不開(kāi)地基、柱子、層面和墻體這些組成部分,建筑工人就是把這些組成部分一個(gè)個(gè)建起來(lái),最后連成一體建出一棟棟樓房。
三、建造者模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
1.客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過(guò)程解耦,使得相同的創(chuàng)建過(guò)程可以創(chuàng)建不同的產(chǎn)品對(duì)象。
2.每一個(gè)具體建造者都獨(dú)立,因此可以方便地替換具體建造者或增加新的具體建造者, 用戶使用不同的具體建造者即可得到不同的產(chǎn)品對(duì)象 。
3.可以更加精細(xì)地控制產(chǎn)品的創(chuàng)建過(guò)程 。將復(fù)雜產(chǎn)品的創(chuàng)建步驟分解在不同的方法中,使得創(chuàng)建過(guò)程更加清晰,也更方便使用程序來(lái)控制創(chuàng)建過(guò)程。
4.增加新的具體建造者無(wú)須修改原有類(lèi)庫(kù)的代碼,指揮者類(lèi)針對(duì)抽象建造者類(lèi)編程,系統(tǒng)擴(kuò)展方便,符合“開(kāi)閉”。
缺點(diǎn)
1.當(dāng)建造者過(guò)多時(shí),會(huì)產(chǎn)生很多類(lèi),難以維護(hù)。
2.建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點(diǎn),其組成部分相似,若產(chǎn)品之間的差異性很大,則不適合使用該模式,因此其使用范圍受到一定限制。
3.若產(chǎn)品的內(nèi)部變化復(fù)雜,可能會(huì)導(dǎo)致需要定義很多具體建造者類(lèi)來(lái)實(shí)現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大。
四、工廠模式和建造者模式的對(duì)比
工廠模式用于處理 如何獲取實(shí)例對(duì)象 問(wèn)題,建造者模式用于處理如何建造實(shí)例對(duì)象 問(wèn)題
建造者模式與工廠模式是極為相似的,總體上,建造者模式僅僅只比工廠模式多了一個(gè)“指揮類(lèi)”的角色。在建造者模式的類(lèi)圖中,假如把這個(gè)指揮類(lèi)看做是最終調(diào)用的客戶端,那么剩余的部分就可以看作是一個(gè)簡(jiǎn)單的工廠模式了。
與工廠模式相比,建造者模式一般用來(lái)創(chuàng)建更為復(fù)雜的對(duì)象,因?yàn)閷?duì)象的創(chuàng)建過(guò)程更為復(fù)雜,因此將對(duì)象的創(chuàng)建過(guò)程獨(dú)立出來(lái)組成一個(gè)新的類(lèi)——指揮類(lèi)。
也就是說(shuō),工廠模式是將對(duì)象的全部創(chuàng)建過(guò)程封裝在工廠類(lèi)中,由工廠類(lèi)向客戶端提供最終的產(chǎn)品;而建造者模式中,建造者類(lèi)一般只提供產(chǎn)品類(lèi)中各個(gè)組件的建造,而將具體建造過(guò)程交付給指揮類(lèi)。由指揮類(lèi)負(fù)責(zé)將各個(gè)組件按照特定的規(guī)則組建為產(chǎn)品,然后將組建好的產(chǎn)品交付給客戶端。
五、建造者模式的實(shí)現(xiàn)
Product類(lèi)---產(chǎn)品類(lèi),由多個(gè)部件組成
//Product類(lèi),由多個(gè)部件組成
public class Product
{
List<string> parts = new List<string>();
//添加產(chǎn)品部件
public void Add(string part)
{
parts.Add(part);
}
public void show()
{
Console.WriteLine("\n 創(chuàng)建產(chǎn)品");
foreach (var item in parts)
{
Console.WriteLine("item");
}
}
}
Builder類(lèi)---抽象建造者類(lèi),確定產(chǎn)品由兩個(gè)部件PartA和PartB組成,并聲明一個(gè)得到產(chǎn)品建造后結(jié)果的方法GetResult
abstract class Builder
{
public abstract void BuilderPartA();
public abstract void BuilderPartB();
public abstract Product GetResult();
}
具體建造者類(lèi)
//ConcreteBuilder1類(lèi)---具體建造者類(lèi)
class ConcreteBuilder1 : Builder
{
private Product product = new Product();
//建造具體的兩個(gè)部件
public override void BuilderPartA()
{
product.Add("部件A");
}
public override void BuilderPartB()
{
product.Add("部件B");
}
public override Product GetResult()
{
return product;
}
}
//ConcreteBuilder2類(lèi)---具體建造者類(lèi)
class ConcreteBuilder2 : Builder
{
private Product product = new Product();
//建造具體的兩個(gè)部件
public override void BuilderPartA()
{
product.Add("部件X");
}
public override void BuilderPartB()
{
product.Add("部件Y");
}
public override Product GetResult()
{
return product;
}
}
Director類(lèi)---指揮者類(lèi)
class Director
{
public void Construct(Builder builder)
{
//用來(lái)指揮建造過(guò)程
builder.BuilderPartA();
builder.BuilderPartB();
}
}
客戶端代碼---客戶不需知道具體的建造過(guò)程
static void Main(string[] args)
{
Director director = new Director();
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
//指揮者用ConcreteBuilder1方法建造產(chǎn)品
director.Construct(b1);
Product p1 = b1.GetResult();
p1.show();
//指揮者用ConcreteBuilder2方法建造產(chǎn)品
director.Construct(b2);
Product p2 = b2.GetResult();
p2.show();
Console.Read();
}
六、總結(jié)
建造者模式的使用場(chǎng)合是當(dāng)創(chuàng)建復(fù)雜對(duì)象時(shí),把創(chuàng)建對(duì)象成員和裝配方法分離出來(lái),放在建造者類(lèi)中去實(shí)現(xiàn),用戶使用該復(fù)雜對(duì)象時(shí),不用理會(huì)它的創(chuàng)建和裝配過(guò)程,只關(guān)心它的表示形式。
其實(shí)完全理解這個(gè)模式還是要一番思考的,難以搞懂的是指揮者似乎沒(méi)什么存在的必要,在代碼里也沒(méi)體現(xiàn)它的作用,我們也可以把指揮者的方法放在建造者里面,但為什么沒(méi)有這樣做呢?我想這可能是考慮到單一責(zé)任原則,建造者只負(fù)責(zé)創(chuàng)建對(duì)象的各個(gè)部分,至于各個(gè)部分創(chuàng)建的順序、裝配方法它就不管了。還有就是當(dāng)順序要改變時(shí),建造者可以不用改動(dòng),改動(dòng)指揮者就好了,指揮者只有一個(gè),建造者有很多,要改建造者就麻煩了。
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
java有界類(lèi)型參數(shù)的實(shí)例用法
小編給大家整理了一篇關(guān)于java有界類(lèi)型參數(shù)的使用的相關(guān)文章及擴(kuò)展實(shí)例內(nèi)容,有需要的朋友們可以學(xué)習(xí)參考下。2021-07-07
nacos客戶端一致性hash負(fù)載需求實(shí)現(xiàn)
這篇文章主要介紹了nacos客戶端一致性hash負(fù)載的需求實(shí)現(xiàn)過(guò)程及步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02
Springboot集成JUnit5優(yōu)雅進(jìn)行單元測(cè)試的示例
這篇文章主要介紹了Springboot集成JUnit5優(yōu)雅進(jìn)行單元測(cè)試的示例,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下2020-10-10
spring boot@EnableXXXX注解編程模型講解
這篇文章主要介紹了spring boot@EnableXXXX注解編程模型,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
spring+apollo動(dòng)態(tài)獲取yaml格式的配置方式
這篇文章主要介紹了spring+apollo動(dòng)態(tài)獲取yaml格式的配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04

