本筆記摘抄自:http://www.javashuo.com/article/p-dqjtnegm-ds.html,記錄一下學習過程以備後續查用。html
1、引言算法
在現實生活中,咱們常常會遇到一些構成比較複雜的物品。好比電腦,是由CPU、主板、內存條、硬盤、顯卡、機箱等組裝而成的。手機也是複雜物品,設計模式
由主板、各類芯片、RAM、ROM、攝像頭等部件組成。可是不管是電腦仍是手機,它們的組裝過程是固定的。拿手機來講,組裝流水線是固定的、不變的,ide
可是把不一樣的主板和其它組件組裝在一塊兒就會生產出不一樣型號的手機。那麼在軟件系統中是否是也會存在這樣的對象呢?答案是確定的。在軟件系統中咱們學習
也會遇到相似的複雜對象,而且這個複雜對象的各個部分按照必定的算法組合在一塊兒,此時該對象的建立工做就可使用Builder模式了,下面讓咱們詳細看ui
看這個模式吧。spa
2、建造者模式介紹設計
建造者模式(也叫生成器模式):英文名稱--Builder Pattern;分類--建立型。code
2.一、動機(Motivate)htm
在軟件系統中,有時候面臨着「一個複雜對象」的建立工做,其一般由各個部分的子對象用必定的算法構成。因爲需求的變化,這個複雜對象的各個部分經
常面臨着劇烈的變化,可是將它們組合在一塊兒的算法卻相對穩定。如何應對這種變化?如何提供一種「封裝機制」來隔離出「複雜對象的各個部分」的變化,從
而保持系統中的「穩定構建算法」不隨着需求改變而改變?
2.二、意圖(Intent)
將一個複雜對象的構建與其表示相分離,使得一樣的構建過程能夠建立不一樣的表示。——《設計模式》GoF
2.三、結構圖(Structure)
2.四、模式的組成
1)抽象建造者角色(Builder):爲建立一個Product對象的各個部件指定抽象接口,以規範產品對象的各個組成部分的建造。通常而言,此角色規定要實
現複雜對象的哪些部件的建立,並不涉及具體的對象部件的建立。
2)具體建造者(ConcreteBuilder)
I、實現Builder的接口以構造和裝配該產品的各個部件,即實現抽象建造者角色Builder的方法。
II、定義並明確它所建立的表示,即針對不一樣的商業邏輯,具體化複雜對象的各個部分的建立。
III、提供一個檢索產品的接口。
IV、構造一個使用Builder接口的對象,即在指導者的調用下建立產品實例。
3)指導者(Director):調用具體建造者角色以建立產品對象的各個部分。指導者並無涉及具體產品類的信息,真正擁有具體產品的信息是具體建造者
對象。它只負責保證對象各部分完整建立或按某種順序建立。
4)產品角色(Product):建造中的複雜對象。它要包含那些定義組件的類,包括將這些組件裝配成產品的接口。
2.5 建造者模式的代碼實現
如今人們生活水平都提升了,家家都有了家庭轎車,那今天咱們就以汽車組裝爲例來講明Builder模式的實現。
class Program { /// <summary> /// 小轎車類 /// </summary> public sealed class SaloonCar { //小轎車部件集合 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> /// 抽象建造者,它定義了要建立什麼部件和最後建立的結果,可是不是組裝的的類型,切記。 /// </summary> public abstract class Builder { //建立車門 public abstract void BuildSaloonCarDoor(); //建立車輪 public abstract void BuildSaloonCarWheel(); //建立車引擎 public abstract void BuildSaloonCarEngine(); //得到組裝好的小轎車 public abstract SaloonCar GetSaloonCar(); } /// <summary> /// 具體建立者,具體車型的建立者,例如:別克。 /// </summary> public sealed class BuickBuilder : Builder { SaloonCar buickCar = new SaloonCar(); public override void BuildSaloonCarDoor() { buickCar.Add("Buick's door"); } public override void BuildSaloonCarWheel() { buickCar.Add("Buick's wheel"); } public override void BuildSaloonCarEngine() { buickCar.Add("Buick's engine"); } public override SaloonCar GetSaloonCar() { return buickCar; } } /// <summary> /// 具體建立者,具體車型的建立者,例如:奧迪 /// </summary> public sealed class AoDiBuilder : Builder { SaloonCar aoDiCar = new SaloonCar(); public override void BuildSaloonCarDoor() { aoDiCar.Add("Aodi's door"); } public override void BuildSaloonCarWheel() { aoDiCar.Add("Aodi's wheel"); } public override void BuildSaloonCarEngine() { aoDiCar.Add("Aodi's engine"); } public override SaloonCar GetSaloonCar() { return aoDiCar; } } /// <summary> /// 這個類型纔是組裝的 /// Construct方法裏面的實現就是建立複雜對象固定算法的實現,該算法是固定的或者說是相對穩定的。 /// 這我的固然就是老闆了,也就是建造者模式中的指揮者。 /// </summary> public class Director { //組裝汽車 public void Construct(Builder builder) { builder.BuildSaloonCarDoor(); builder.BuildSaloonCarWheel(); builder.BuildSaloonCarEngine(); } } static void Main(string[] args) { #region 建造者模式 Director director = new Director(); Builder buickBuilder = new BuickBuilder(); Builder aoDiBuilder = new AoDiBuilder(); //組裝別克小轎車 director.Construct(buickBuilder); SaloonCar buickCar = buickBuilder.GetSaloonCar(); buickCar.Show(); Console.WriteLine(); //組裝奧迪小轎車 director.Construct(aoDiBuilder); SaloonCar aoDiCar = aoDiBuilder.GetSaloonCar(); aoDiCar.Show(); Console.Read(); #endregion } }
運行結果以下:
3、建造者模式的實現要點
在建造者模式中,指揮者是直接與客戶端打交道的。指揮者將客戶端建立產品的請求轉換爲對各個部件的建造請求,再將這些請求委派給具體的建造者角
色,而具體的建造者角色是完成具體產品的構建工做的,卻不爲客戶所知道。
建造者模式主要用於「分步驟來構建一個複雜的對象」,其中「分步驟」是一個固定的組合過程,而複雜對象的各個部分是常常變化的。 產品不須要抽象類,
由於建造者模式建立出來的最終產品可能差別很大,因此不大可能提煉出一個抽象產品類。 在前面文章中介紹的抽象工廠模式解決了「多系列產品」的需求變
化,而建造者模式解決的是 「產品部分」 的須要變化。 因爲建造者隱藏了具體產品的組裝過程,因此要改變一個產品的內部表示,只須要再實現一個具體的
建造者就能夠了,從而能很好地應對產品組成部件的需求變化。
3.一、建造者模式的優勢
1)使用建造者模式可使客戶端沒必要知道產品內部組成的細節。
2)具體的建造者類之間是相互獨立的,容易擴展。
3)因爲具體的建造者是獨立的,所以能夠對建造過程逐步細化,而不對其餘的模塊產生任何影響。
3.二、建造者模式的缺點
1)產生多餘的Build對象以及Dirextor類。
3.三、建立者模式的使用場景
1)當建立複雜對象的算法應該獨立於該對象的組成部分以及它們的裝配方式時。
2)相同的方法,不一樣的執行順序,產生不一樣的事件結果時。
3)多個部件或零件,均可以裝配到一個對象中,可是產生的運行結果又不相同時。
4)產品類很是複雜,或者產品類中的調用順序不一樣產生了不一樣的效能。
5)建立一些複雜的對象時,這些對象的內部組成構件間的建造順序是穩定的,可是對象的內部組成構件面臨着複雜的變化。
4、.NET中建造者模式的實現
微軟的類庫裏面大量使用了設計模式,若是要想學習設計模式,仔細看看微軟的類庫是頗有幫助的。今天的設計模式在FCL裏面也有實現,該類型的名字
是System.Text.StringBuilder(存在於mscorlib.dll程序集中),它就是一個建造者模式的實現,從名稱也能夠看出來。不過它的實現屬於建造者模式的演化,此時
的建造者模式沒有指揮者角色和抽象建造者角色,StringBuilder類既扮演着具體建造者的角色,也同時扮演了指揮者和抽象建造者的角色。
StringBuilder類扮演着建造string對象的具體建造者角色,其中的ToString()方法用來返回具體產品給客戶端(至關於上面代碼中GetSaloonCar方法)。其中
Append方法用來建立產品的組件(至關於上面代碼中Add方法),由於string對象中每一個組件都是字符,因此也就不須要指揮者角色的代碼(如上面代碼中的
Construct方法),Append方法也充當了指揮者Construct方法的做用。
5、總結
須要重申的是,學習設計模式不能死學,就像StringBuilder同樣,他和Gof23種設計模式中定義的情形有很大的不一樣,可是它也是Builder模式,由於它要解決
的問題和使用場景是吻合的。咱們寫代碼的時候,不要太居於形式,要看使用的契機和模式是否吻合,根據具體的狀況咱們的模式也會發生變化。當咱們看得越
多也寫得越多的時候,變化就越天然了。