設(shè)計(jì)模式之生成器模式
作者:Aaron
來源:SegmentFault 思否社區(qū)
生成器模式又叫做建造者模式,之前介紹的一些創(chuàng)建型的設(shè)計(jì)模式基本都比較簡單的,生成器模式是較為復(fù)雜的創(chuàng)建型模式,它將客戶端與包含多個(gè)組成部分的復(fù)雜對象的創(chuàng)建過程分離,客戶端無須知道復(fù)雜對象的內(nèi)部組成部分與裝配方式,只需要知道所需建造者的類型即可。
它關(guān)注如何一步一步創(chuàng)建一個(gè)的復(fù)雜對象,不同的具體建造者定義了不同的創(chuàng)建過程,且具體建造者相互獨(dú)立,增加新的建造者非常方便,無須修改已有代碼,系統(tǒng)具有較好的拓展性。
生成器模式:是一種設(shè)計(jì)模式,又名:建造模式,是一種對象構(gòu)建模式。它可以將復(fù)雜對象的建造過程抽象出來(抽象類別),使這個(gè)抽象過程的不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)(屬性)的對象?!?節(jié)選自維基百科
例如,我們來思考如何創(chuàng)建一輛汽車對象。創(chuàng)造一輛簡單的汽車,首先需要?jiǎng)?chuàng)建車的框架和車轱轆,然后安裝汽車門、汽車玻璃,最后再安裝上發(fā)動(dòng)機(jī)。但是如果你想要一個(gè)性能更好的汽車的話,那么還需要給汽車加上一些其他的設(shè)施,這個(gè)時(shí)候咱們需要怎么去做呢?
最簡單的方法是拓展原有汽車的基類,然后創(chuàng)建一系列涵蓋所有參數(shù)組合的子類。但最終將面對相當(dāng)數(shù)量的子類。任何新增的參數(shù)都會(huì)讓這個(gè)層次結(jié)構(gòu)更加復(fù)雜。
另一種方法則無需生成子類??梢栽倨嚨幕愔袆?chuàng)建一個(gè)包括所有可能參數(shù)的超級構(gòu)造函數(shù),并用它來控制汽車對象。這種方法可以避免生成子類,但它卻會(huì)造成另外一個(gè)問題。通常情況下,絕大部分的參數(shù)都沒有使用,這使得對于構(gòu)造函數(shù)的調(diào)用十分不簡潔。
生成器模式優(yōu)缺點(diǎn)
生成器模式會(huì)將對象構(gòu)造過程劃分為一組步驟,每次創(chuàng)建對象時(shí),你都需要通過生成器對象執(zhí)行一系列步驟。重點(diǎn)在于你無需調(diào)用所有步驟,而只需調(diào)用創(chuàng)建特定對象配置所需的那些步驟即可。當(dāng)你需要?jiǎng)?chuàng)建不同形式的產(chǎn)品時(shí),其中的一些構(gòu)造步驟可能需要不同的實(shí)現(xiàn)??梢詣?chuàng)建多個(gè)不同的生成器, 用不同方式實(shí)現(xiàn)一組相同的創(chuàng)建步驟。然后你就可以在創(chuàng)建過程中使用這些生成器 (例如按順序調(diào)用多個(gè)構(gòu)造步驟) 來生成不同類型的對象。
優(yōu)點(diǎn)
在生成器模式中,客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過程解耦,使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品對象。 每一個(gè)具體建造者都相對獨(dú)立,而與其他的具體建造者無關(guān),因此可以很方便地替換具體建造者或增加新的具體建造者,用戶使用不同的具體建造者即可得到不同的產(chǎn)品對象。由于指揮者類針對抽象建造者編程,增加新的具體建造者無須修改原有類庫的代碼,系統(tǒng)擴(kuò)展方便,符合開閉原則 可以更加精細(xì)地控制產(chǎn)品的創(chuàng)建過程。將復(fù)雜產(chǎn)品的創(chuàng)建步驟分解在不同的方法中,使得創(chuàng)建過程更加清晰,也更方便使用程序來控制創(chuàng)建過程。
生成器模式所生成的產(chǎn)品一般具有較多的共同點(diǎn),其組成部分相似,如果產(chǎn)品之間的差異性很大,例如很多組成部分都不相同,不適合使用建造者模式,因此其使用范圍受到一定的限制 如果產(chǎn)品的內(nèi)部變化復(fù)雜,可能會(huì)導(dǎo)致需要定義很多具體建造者類來實(shí)現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大,增加系統(tǒng)的理解難度和運(yùn)行成本
生成器:接口生命再所有類型生成器中通用的產(chǎn)品構(gòu)造步驟 具體生成器:提供構(gòu)造過程的不同實(shí)現(xiàn)。具體生成器也可以構(gòu)造不遵循通用接口的產(chǎn)品 產(chǎn)品:是最終生成的對象。由不同生成器構(gòu)造的產(chǎn)品無需屬于同一類層次構(gòu)造或接口 指揮者:定義調(diào)用構(gòu)造步驟的順序,這樣你就可以創(chuàng)建和服用特定的產(chǎn)品配置 客戶端:必須將某個(gè)生成器對象與主管類關(guān)聯(lián),一般情況下,你只需要通過指揮者類構(gòu)造函數(shù)的參數(shù)進(jìn)行一次性關(guān)聯(lián)即可

//?抽象建造者
abstract?class?Builder?{
????public?abstract?buildPartA():void;
????public?abstract?buildPartB():void;
????public?abstract?buildPartC():void;
????public?abstract?buildProduct():Product;
}
//?具體建造者
class?ConcreteBuilder?extends?Builder?{
????private?product:Product;
????constructor(product:Product)?{
????????super();
????????this.product?=?product;
????}
????public?buildPartA():void?{}
????public?buildPartB():void?{}
????public?buildPartC():void?{}
????//?最終組建一個(gè)產(chǎn)品
????public?buildProduct():Product?{
????????return?this.product;
????}
}
//?產(chǎn)品角色
class?Product?{
????public?doSomething():void?{
????????//?獨(dú)立業(yè)務(wù)
????}
}
//?指揮者
class?Director?{
????private?_builder:Builder;
????constructor(builder:Builder)?{
????????this._builder?=?builder;
????}
????set?builder(builder:Builder)?{
????????this._builder?=?builder;
????}
????//?將處理建造的流程交給指揮者
????public?constructorProduct()?{
????????this._builder.buildPartA();
????????this._builder.buildPartB();
????????this._builder.buildPartC();
????????return?this._builder.buildProduct();
????}
}
//?使用
const?builder:Builder?=?new?ConcreteBuilder(new?Product());
const?director:Director?=?new?Director(builder);
const?product:Product?=?director.constructorProduct();

