C#设计模式系列:建造者模式(Builder)
1 建造者模式简介
1.1 定义
建造者模式(Builder)将复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
1.2 使用频率
中低
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无关
◊ 可使对构造过程更加精细控制
◊ 将构建代码和表示代码分开
◊ 建造者模式的缺点在于难于应付分步骤构建算法的需求变动