一、定義
將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。建造者模式是一種對象創建型模式。
二、結構
角色
- Builder(抽象建造者):它為創建一個產品Product對象的各個部件指定抽象接口,在該接口中一般聲明兩類方法,一類方法是buildPartX(),它們用於創建復雜對象的各個部件;另一類方法是getResult(),它們用於返回復雜對象。Builder既可以是抽象類,也可以是接口。
- ConcreteBuilder(具體建造者):它實現了Builder接口,實現各個部件的具體構造和裝配方法,定義並明確它所創建的復雜對象,也可以提供一個方法返回創建好的復雜產品對象。
- Product(產品角色):它是被構建的復雜對象,包含多個組成部件,具體建造者創建該產品的內部表示並定義它的裝配過程。在本類圖中,產品類是一個具體的類,而非抽象類。實際編程中,產品類可以是由一個抽象類與它的不同實現組成,也可以是由多個抽象類與他們的實現組成。
- Director(指揮者):指揮者又稱為導演類,負責調用適當的建造者來組建產品,導演類一般不與產品類發生依賴關系,與導演類直接交互的是建造者類。一般來說,導演類被用來封裝程序中易變的部分。
三、實現
背景:模擬生產各種筆(這里假設筆的零件生產是有順序的:筆芯 -> 筆殼 -> 組裝)
namespace DesignPatterns.Builder { class Program { static void Main(string[] args) { PenDirector director = new PenDirector(); Pen ballpointpen = director.ConstructPen(new BallpointPenBuilder()); Pen brushpen = director.ConstructPen(new BrushPenBuilder()); } } /// <summary> /// 創建抽象產品類 -- 筆 /// </summary> public abstract class Pen { /**筆芯**/ private string _cartridge; /**外殼**/ private string _shell; public string GetCartridge() { return _cartridge; } public void SetCartridge(string cartridge) { this._cartridge = cartridge; } public string GetShell() { return _shell; } public void SetShell(string shell) { this._shell = shell; } } public interface IPenBuilder { /** * 生產筆芯 */ void BuildCartridge(); /** * 生產外殼 */ void BuildShell(); /** * 組裝筆 */ Pen BuildPen(); } /// <summary> /// 具體產品類 -- 圓珠筆 /// </summary> public class BallpointPen : Pen { public BallpointPen() { Console.WriteLine("生產組裝圓珠筆"); } } /// <summary> /// 具體產品類 -- 畫筆 /// </summary> public class BrushPen : Pen { public BrushPen() { Console.WriteLine("生產組裝畫筆"); } } /// <summary> /// 建造者(具體) -- 圓珠筆builder /// </summary> public class BallpointPenBuilder : IPenBuilder { Pen _pen; public BallpointPenBuilder() { _pen = new BallpointPen(); } public void BuildCartridge() { _pen.SetCartridge("圓珠筆筆芯"); } public void BuildShell() { _pen.SetShell("圓珠筆外殼"); } public Pen BuildPen() { return _pen; } } /// <summary> /// 建造者(具體) -- 畫筆builder /// </summary> public class BrushPenBuilder : IPenBuilder { Pen _pen; public BrushPenBuilder() { _pen = new BrushPen(); } public void BuildCartridge() { _pen.SetCartridge("畫筆筆芯"); } public void BuildShell() { _pen.SetShell("畫筆外殼"); } public Pen BuildPen() { return _pen; } } /// <summary> /// 導演類 Director /// </summary> public class PenDirector { public Pen ConstructPen(IPenBuilder penBuilder) { //生產筆芯 penBuilder.BuildCartridge(); //生產外殼 penBuilder.BuildShell(); //組裝筆 return penBuilder.BuildPen(); } } }
四、適用場景
需要生成的產品對象有復雜的內部結構,這些產品對象通常包含多個成員屬性。
需要生成的產品對象的屬性相互依賴,需要指定其生成順序。
對象的創建過程獨立於創建該對象的類。在建造者模式中通過引入了指揮者類,將創建過程封裝在指揮者類中,而不在建造者類和客戶類中。
隔離復雜對象的創建和使用,並使得相同的創建過程可以創建不同的產品。
五、優缺點
優點:
封裝性很好:使用建造者模式可以有效的封裝變化,在使用建造者模式的場景中,一般產品類和建造者類是比較穩定的,因此,將主要的業務邏輯封裝在導演類中對整體而言可以取得比較好的穩定性。
擴展性很好:建造者模式很容易進行擴展。如果有新的需求,通過實現一個新的建造者類就可以完成,基本上不用修改之前已經測試通過的代碼,因此也就不會對原有功能引入風險。
有效控制細節風險:由於具體的建造者是獨立的,因此可以對建造者過程逐步細化,而不對其他的模塊產生任何影響。
缺點:
建造者模式所創建的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用范圍受到一定的限制。
如果產品的內部變化復雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。
歡迎閱讀本系列文章:Head First設計模式之目錄