1、建造者模式簡介
1.1>、定義
建造者模式(Builder)將複雜的構建與其表示相分離,使得同樣的構建過程可以建立不同的表示。
1.2>、使用頻率
中低
1.3>、原型模式應用
在軟體系統中,有時候面臨一個複雜物件的建立工作,該物件通常由各個部分子物件用一定的演算法構成,或者按一定的步驟組合而成;這些演算法和步驟是穩定的,而構成這個物件的子物件卻經常由於需求的變化而不斷變化。
生活中的例子,要組裝一臺電腦,它的組裝過程基本是不變的,都可以由主機板、CPU、記憶體等按照某個穩定方式組合而成。然而主機板、CPU、記憶體等零件本身都是可能多變的。將記憶體等這種易變的零件與電腦的其他部件分離,實現解耦合,則可以輕鬆實現電腦不斷升級。
2、建造者模式結構
2.1>、結構圖
2.2>、參與者
建造者模式參與者:
◊ Builder:為建立一個Product物件的各個部件指定抽象介面;
◊ ConcreteBuilder
° 實現Builder的介面以構造和裝配該產品的各個部件
° 定義並明確它所建立的表示
° 提供一個檢索Product的介面
◊ Director:構造一個使用Builder介面的物件;
◊ Product
° 表示被構造的複雜物件。ConcreteBuilder建立該產品的內部表示並定義它的裝配過程
° 包含定義組成部件的類,包括將這些部件裝配成最終產品的介面
在建造者模式中,Director規定了建立一個物件所需要的步驟和次序,Builder則提供了一些列完成這些步驟的方法,ConcreteBuilder給出了這些方法的具體實現,是物件的直接建立者。
3、建造者模式結構實現
Product.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Structural { public class Product { private List<string> _parts = new List<string>(); public void Add(string part) { _parts.Add(part); } public void Show() { Console.WriteLine("Product Parts"); foreach (string part in _parts) { Console.WriteLine(part); } } } }
Builder.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Structural { public abstract class Builder { public abstract void BuildPartA(); public abstract void BuildPartB(); public abstract Product GetResult(); } }
ConcreteBuilder1.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Structural { public class ConcreteBuilder1 : Builder { private Product _product = new Product(); public override void BuildPartA() { _product.Add("PartA"); } public override void BuildPartB() { _product.Add("PartB"); } public override Product GetResult() { return _product; } } }
ConcreteBuilder2.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Structural { public class ConcreteBuilder2 : Builder { private Product _product = new Product(); public override void BuildPartA() { _product.Add("PartX"); } public override void BuildPartB() { _product.Add("PartY"); } public override Product GetResult() { return _product; } } }
Director.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Structural { public class Director { /// <summary> /// Builder uses a complex series of steps /// </summary> public void Construct(Builder builder) { builder.BuildPartA(); builder.BuildPartB(); } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.BuilderPattern.Structural; namespace DesignPatterns.BuilderPattern { class Program { static void Main(string[] args) { // Create director and builders Director director = new Director(); Builder b1 = new ConcreteBuilder1(); Builder b2 = new ConcreteBuilder2(); // Construct two products director.Construct(b1); Product p1 = b1.GetResult(); p1.Show(); director.Construct(b2); Product p2 = b2.GetResult(); p2.Show(); } } }
執行輸出:
Product Parts
PartA
PartB
Product Parts
PartX
PartY
請按任意鍵繼續. . .
4、建造者模式實踐應用
Vehicle.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Practical { /// <summary> /// The 'Product' class /// </summary> public class Vehicle { private string _vehicleType; private Dictionary<string, string> _parts = new Dictionary<string, string>(); /// <summary> /// Constructor /// </summary> public Vehicle(string vehicleType) { this._vehicleType = vehicleType; } /// <summary> /// Indexer /// </summary> public string this[string key] { get { return _parts[key]; } set { _parts[key] = value; } } public void Show() { Console.WriteLine("\n---------------------------"); Console.WriteLine("Vehicle Type: {0}", _vehicleType); Console.WriteLine(" Frame : {0}", _parts["frame"]); Console.WriteLine(" Engine : {0}", _parts["engine"]); Console.WriteLine(" #Wheels: {0}", _parts["wheels"]); Console.WriteLine(" #Doors : {0}", _parts["doors"]); } } }
VehicleBuilder.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Practical { /// <summary> /// The 'Builder' abstract class /// </summary> public abstract class VehicleBuilder { protected Vehicle vehicle; // Gets vehicle instance public Vehicle Vehicle { get { return vehicle; } } // Abstract build methods public abstract void BuildFrame(); public abstract void BuildEngine(); public abstract void BuildWheels(); public abstract void BuildDoors(); } }
MotorCycleBuilder.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Practical { public class MotorCycleBuilder : VehicleBuilder { public MotorCycleBuilder() { vehicle = new Vehicle("MotorCycle"); } public override void BuildFrame() { vehicle["frame"] = "MotorCycle Frame"; } public override void BuildEngine() { vehicle["engine"] = "500 cc"; } public override void BuildWheels() { vehicle["wheels"] = "2"; } public override void BuildDoors() { vehicle["doors"] = "0"; } } }
CarBuilder.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Practical { public class CarBuilder : VehicleBuilder { public CarBuilder() { vehicle = new Vehicle("Car"); } public override void BuildFrame() { vehicle["frame"] = "Car Frame"; } public override void BuildEngine() { vehicle["engine"] = "2500 cc"; } public override void BuildWheels() { vehicle["wheels"] = "4"; } public override void BuildDoors() { vehicle["doors"] = "4"; } } }
ScooterBuilder.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Practical { public class ScooterBuilder : VehicleBuilder { public ScooterBuilder() { vehicle = new Vehicle("Scooter"); } public override void BuildFrame() { vehicle["frame"] = "Scooter Frame"; } public override void BuildEngine() { vehicle["engine"] = "50 cc"; } public override void BuildWheels() { vehicle["wheels"] = "2"; } public override void BuildDoors() { vehicle["doors"] = "0"; } } }
Shop.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.BuilderPattern.Practical { public class Shop { public void Construct(VehicleBuilder vehicleBuilder) { vehicleBuilder.BuildFrame(); vehicleBuilder.BuildEngine(); vehicleBuilder.BuildWheels(); vehicleBuilder.BuildDoors(); } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.BuilderPattern.Practical; namespace DesignPatterns.BuilderPattern { class Program { static void Main(string[] args) { VehicleBuilder builder; // Create shop with vehicle builders Shop shop = new Shop(); // Construct and display vehicles builder = new ScooterBuilder(); shop.Construct(builder); builder.Vehicle.Show(); builder = new CarBuilder(); shop.Construct(builder); builder.Vehicle.Show(); builder = new MotorCycleBuilder(); shop.Construct(builder); builder.Vehicle.Show(); } } }
執行輸出:
--------------------------- Vehicle Type: Scooter Frame : Scooter Frame Engine : 50 cc #Wheels: 2 #Doors : 0 --------------------------- Vehicle Type: Car Frame : Car Frame Engine : 2500 cc #Wheels: 4 #Doors : 4 --------------------------- Vehicle Type: MotorCycle Frame : MotorCycle Frame Engine : 500 cc #Wheels: 2 #Doors : 0 請按任意鍵繼續. . .
5、建造者模式應用分析
建造者模式適用情形:
◊ 需要生成的產品物件有複雜的內部結構
◊ 需要生成的產品物件的屬性相互依賴,建造者模式可以強迫生成順序
◊ 在物件建立過程中會使用到系統中的一些其他物件,這些物件在產品物件的建立過程中不易得到
建造者模式特點:
◊ 建造者模式的使用使得產品的內部表物件可以獨立地變化。使用建造者模式可以使客戶不必知道產品內部組成的細節
◊ 每一個Builder都相對獨立,而與其他Builder無關
◊ 可使對構造過程更加精細控制
◊ 將構建程式碼和表示程式碼分開
◊ 建造者模式的缺點在於難於應付分步驟構建演算法的需求變動