.Net創(chuàng)建型設(shè)計模式之建造者、生成器模式(Builder)
一、動機(jī)(Motivation)
在軟件系統(tǒng)中,有時候面臨著“一個復(fù)雜對象”的創(chuàng)建工作,其通常由各個部分的子對象用一定的算法構(gòu)成;由于需求的變化,這個復(fù)雜對象的各個部分經(jīng)常面臨著劇烈的變化,但是將它們組合在一起的算法卻相對穩(wěn)定。
如何應(yīng)對這種變化?如何提供一種“封裝機(jī)制”來隔離出“復(fù)雜對象的各個部分”的變化,從而保持系統(tǒng)中的“穩(wěn)定構(gòu)建算法”不隨著需求改變而改變?
二、意圖(Intent)
將一個復(fù)雜對象的構(gòu)建與其表示相分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。——《設(shè)計模式》GoF
三、結(jié)構(gòu)(Structure)
協(xié)作(Collaborations)
四、模式的組成
(1)、抽象建造者角色(Builder):為創(chuàng)建一個Product對象的各個部件指定抽象接口,以規(guī)范產(chǎn)品對象的各個組成成分的建造。一般而言,此角色規(guī)定要實現(xiàn)復(fù)雜對象的哪些部分的創(chuàng)建,并不涉及具體的對象部件的創(chuàng)建。
(2)、具體建造者(ConcreteBuilder)
1)實現(xiàn)Builder的接口以構(gòu)造和裝配該產(chǎn)品的各個部件。即實現(xiàn)抽象建造者角色Builder的方法。
2)定義并明確它所創(chuàng)建的表示,即針對不同的商業(yè)邏輯,具體化復(fù)雜對象的各部分的創(chuàng)建
3) 提供一個檢索產(chǎn)品的接口
4) 構(gòu)造一個使用Builder接口的對象即在指導(dǎo)者的調(diào)用下創(chuàng)建產(chǎn)品實例
(3)、指導(dǎo)者(Director):調(diào)用具體建造者角色以創(chuàng)建產(chǎn)品對象的各個部分。指導(dǎo)者并沒有涉及具體產(chǎn)品類的信息,真正擁有具體產(chǎn)品的信息是具體建造者對象。它只負(fù)責(zé)保證對象各部分完整創(chuàng)建或按某種順序創(chuàng)建。
(4)、產(chǎn)品角色(Product):建造中的復(fù)雜對象。它要包含那些定義組件的類,包括將這些組件裝配成產(chǎn)品的接口。
五、建筑者模式的具體實現(xiàn)
現(xiàn)在人們的生活水平都提高了,有錢了,我今天就以汽車組裝為例子。每臺汽車的組裝過程都是一致的,所以我們使用同樣的構(gòu)建過程可以創(chuàng)建不同的表示(即可以組裝成不同型號的汽車,不能像例子這樣,一會別克,一會奧迪的)
組裝汽車、電腦、手機(jī)、電視等等負(fù)責(zé)對象的這些場景都可以應(yīng)用建造者模式來設(shè)計。
static void Main(string[] args) { Director director = new Director(); Builder buickCarBuilder = new BuickBuilder(); Builder aoDiCarBuilder = new AoDiBuilder(); director.Construct(buickCarBuilder); Car buickCar = buickCarBuilder.GetCar(); //組裝完成,我來駕駛別克了 buickCar.Show(); director.Construct(aoDiCarBuilder); // 我老婆就要奧迪了,她比較喜歡大品牌 Car aoDiCar = aoDiCarBuilder.GetCar(); aoDiCar.Show(); } /// <summary> /// 這個類型才是組裝的,Construct方法里面的實現(xiàn)就是創(chuàng)建復(fù)雜對象固定算法的實現(xiàn),該算法是固定的,或者說是相對穩(wěn)定的 /// 這個人當(dāng)然就是老板了,也就是建造者模式中的指揮者 /// </summary> public class Director { // 組裝汽車 public void Construct(Builder builder) { builder.BuildCarDoor(); builder.BuildCarWheel(); builder.BuildCarEngine(); } } /// <summary> /// 汽車類 /// </summary> public sealed class Car { // 汽車部件集合 private IList<string> parts = new List<string>(); // 把單個部件添加到汽車部件集合中 public void Add(string part) { parts.Add(part); } public void Show() { Console.WriteLine("汽車開始在組裝......."); foreach (string part in parts) { Console.WriteLine("組件" + part + "已裝好"); } Console.WriteLine("汽車組裝好了"); } } /// <summary> /// 抽象建造者,它定義了要創(chuàng)建什么部件和最后創(chuàng)建的結(jié)果,但是不是組裝的的類型,切記 /// </summary> public abstract class Builder { // 創(chuàng)建車門 public abstract void BuildCarDoor(); // 創(chuàng)建車輪 public abstract void BuildCarWheel(); //創(chuàng)建車引擎 public abstract void BuildCarEngine(); // 獲得組裝好的汽車 public abstract Car GetCar(); } /// <summary> /// 具體創(chuàng)建者,具體的車型的創(chuàng)建者,例如:別克 /// </summary> public sealed class BuickBuilder : Builder { Car buickCar = new Car(); public override void BuildCarDoor() { buickCar.Add("Buick's Door"); } public override void BuildCarWheel() { buickCar.Add("Buick's Wheel"); } public override void BuildCarEngine() { buickCar.Add("Buick's Engine"); } public override Car GetCar() { return buickCar; } } /// <summary> /// 具體創(chuàng)建者,具體的車型的創(chuàng)建者,例如:奧迪 /// </summary> public sealed class AoDiBuilder : Builder { Car aoDiCar = new Car(); public override void BuildCarDoor() { aoDiCar.Add("Aodi's Door"); } public override void BuildCarWheel() { aoDiCar.Add("Aodi's Wheel"); } public override void BuildCarEngine() { aoDiCar.Add("Aodi's Engine"); } public override Car GetCar() { return aoDiCar; } }
六、建造者模式的實現(xiàn)要點
在建造者模式中,指揮者是直接與客戶端打交道的,指揮者將客戶端創(chuàng)建產(chǎn)品的請求劃分為對各個部件的建造請求,再將這些請求委派到具體建造者角色,具體建造者角色是完成具體產(chǎn)品的構(gòu)建工作的,卻不為客戶所知道。建造者模式主要用于“分步驟來構(gòu)建一個復(fù)雜的對象”,其中“分步驟”是一個固定的組合過程,而復(fù)雜對象的各個部分是經(jīng)常變化的。 產(chǎn)品不需要抽象類,由于建造模式的創(chuàng)建出來的最終產(chǎn)品可能差異很大,所以不大可能提煉出一個抽象產(chǎn)品類。
在前面文章中介紹的抽象工廠模式解決了“系列產(chǎn)品”的需求變化,而建造者模式解決的是 “產(chǎn)品部分” 的需要變化。
由于建造者隱藏了具體產(chǎn)品的組裝過程,所以要改變一個產(chǎn)品的內(nèi)部表示,只需要再實現(xiàn)一個具體的建造者就可以了,從而能很好地應(yīng)對產(chǎn)品組成組件的需求變化。
1、建造者模式的優(yōu)點:
(1)、使用建造者模式可以使客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié)。
(2)、具體的建造者類之間是相互獨立的,容易擴(kuò)展。
(3)、由于具體的建造者是獨立的,因此可以對建造過程逐步細(xì)化,而不對其他的模塊產(chǎn)生任何影響。
2、建造者模式的缺點:
產(chǎn)生多余的Build對象以及Dirextor類。
3、創(chuàng)建者模式的使用場景:
(1)、當(dāng)創(chuàng)建復(fù)雜對象的算法應(yīng)該獨立于該對象的組成部分以及它們的裝配方式時。
(2)、相同的方法,不同的執(zhí)行順序,產(chǎn)生不同的事件結(jié)果時。
(3)、多個部件或零件,都可以裝配到一個對象中,但是產(chǎn)生的運(yùn)行結(jié)果又不相同時。
(4)、產(chǎn)品類非常復(fù)雜,或者產(chǎn)品類中的調(diào)用順序不同產(chǎn)生了不同的效能。
(5)、創(chuàng)建一些復(fù)雜的對象時,這些對象的內(nèi)部組成構(gòu)件間的建造順序是穩(wěn)定的,但是對象的內(nèi)部組成構(gòu)件面臨著復(fù)雜的變化。
七、.NET框架中的Builder應(yīng)用
在ASP.Net中,我們在寫一個Page類時,這個類繼承自System.Web.UI.Page。Page其實就是一個Builder,它是一個容器。它有很多方法,就是所謂的BuilderPart()方法,例如:OnInit()、OnLoad()、OnPreRender()、Render()等,它們都是虛方法,我們都可以去重寫,提供我們自己的實現(xiàn)。當(dāng)我們編譯到bin文件夾下的dll時,我們就生成了一個我們自己的ConcreteBuilder實例。實際上系統(tǒng)使用的是Page基類。
到此這篇關(guān)于.Net設(shè)計模式之建造者、生成器模式(Builder)的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ASP.NET實現(xiàn)word文檔在線預(yù)覽功能代碼
文檔管理系統(tǒng)需要實現(xiàn)WORD能在線預(yù)覽功能,以前覺得挺難的,經(jīng)過一番研究發(fā)現(xiàn),WORD自帶的另存為可以保存為HTMl文件。2010-07-07部署ASP.NET?Core程序到Windows系統(tǒng)
這篇文章介紹了部署ASP.NET?Core程序到Windows系統(tǒng)的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03.Net結(jié)構(gòu)型設(shè)計模式之橋接模式(Bridge)
這篇文章介紹了.Net結(jié)構(gòu)型設(shè)計模式之橋接模式(Bridge),文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05