建造者模式(Builder),將一個複製對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。javascript
建造者模式的UML圖:html
Builder是爲建立一個Product對象的各個部件指定的抽象接口。java
ConcreteBuilder是具體的建造者,實現Builder接口,構造和裝備各個部件。git
Product是產品角色,也就是具體的產品。算法
Director是指揮者,它是構建一個使用Builder接口的對象。設計模式
如下給出建造者模式的基本代碼結構:ide
namespace ConsoleApplication1 { //Product類 class Product { 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); } } } //Builder類 abstract class Builder { public abstract void BuildPartA(); public abstract void BuildPartB(); public abstract Product GetResult(); } //ConcreteBuild1類 class ConcreteBuilder1 : Builder { private Product product = new Product(); public override void BuildPartA() //建造具體的兩個部件是部件A和部件B { product.Add("部件A"); } public override void BuildPartB() { product.Add("部件B"); } public override Product GetResult() { return product; } } //ConcreteBuild1類 class ConcreteBuilder2 : Builder { private Product product = new Product(); public override void BuildPartA() //建造兩個部件是部件X和部件Y { product.Add("部件X"); } public override void BuildPartB() { product.Add("部件Y"); } public override Product GetResult() { return product; } } //Director指揮者類 class Director { public void Construct(Builder builder) { builder.BuildPartA(); //用來指揮建造過程 builder.BuildPartB(); } } class Program { static void Main(string[] args) { Director director = new Director(); Builder b1 = new ConcreteBuilder1(); Builder b2 = new ConcreteBuilder2(); director.Construct(b1); Product p1 = b1.GetResult(); //指揮者用ConcreteBuilder1的方法來建造產品 p1.Show(); director.Construct(b2); Product p2 = b2.GetResult(); //指揮者用ConcreteBuilder2的方法來建造產品 p2.Show(); Console.ReadKey(); } } }
回到《大話設計模式》裏的造人的例子:函數
namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { Pen p = new Pen(Color.Blue); PersonThinBuilder ptb = new PersonThinBuilder(pictureBox1.CreateGraphics(), p); PersonDirector pdThin = new PersonDirector(ptb); pdThin.CreatePerson(); PersonFatBuilder pfb = new PersonFatBuilder(pictureBox2.CreateGraphics(), p); PersonDirector pdFat = new PersonDirector(pfb); pdFat.CreatePerson(); } } abstract class PersonBuilder { protected Graphics g; protected Pen p; public PersonBuilder(Graphics g, Pen p) { this.g = g; this.p = p; } //造人都必需要有頭,身體,左右手,左右腳,都必須共有的提取出來做爲抽象方法限制其子類必須有 public abstract void BuildHead(); public abstract void BuildBody(); public abstract void BuildArmLeft(); public abstract void BuildArmRight(); public abstract void BuildLegLeft(); public abstract void BuildLegRight(); } //瘦人建造類,具體的建造過程 class PersonThinBuilder : PersonBuilder { public PersonThinBuilder(Graphics g, Pen p) : base(g, p) { } public override void BuildHead() { g.DrawEllipse(p, 50, 20, 30, 30); } public override void BuildBody() { g.DrawRectangle(p, 60, 50, 10, 50); } public override void BuildArmLeft() { g.DrawLine(p, 60, 50, 40, 100); } public override void BuildArmRight() { g.DrawLine(p, 70, 50, 90, 100); } public override void BuildLegLeft() { g.DrawLine(p, 60, 100, 45, 150); } public override void BuildLegRight() { g.DrawLine(p, 70, 100, 85, 150); } } //肥人建造類,具體的建造過程 class PersonFatBuilder : PersonBuilder { public PersonFatBuilder(Graphics g, Pen p): base(g, p) { } public override void BuildHead() { g.DrawEllipse(p, 50, 20, 30, 30); } public override void BuildBody() { g.DrawRectangle(p, 45, 50, 40, 50); } public override void BuildArmLeft() { g.DrawLine(p, 60, 50, 40, 100); } public override void BuildArmRight() { g.DrawLine(p, 70, 50, 90, 100); } public override void BuildLegLeft() { g.DrawLine(p, 60, 100, 45, 150); } public override void BuildLegRight() { g.DrawLine(p, 70, 100, 85, 150); } } //指揮者類Director class PersonDirector { private PersonBuilder pb; public PersonDirector(PersonBuilder pb) { this.pb = pb; } public void CreatePerson() //裝配方法 控制裝配過程 { pb.BuildHead(); pb.BuildBody(); pb.BuildArmLeft(); pb.BuildArmRight(); pb.BuildLegLeft(); pb.BuildLegRight(); } } }
生成結果以下圖所示:post
建造者模式使用注意點:共同要有的東西,例如頭,身體,左手,右手,左腳,右腳等,提取出來設成抽象函數,這樣就可以避免遺漏。同時,指揮者類放裝配方法。控制創造過程。學習
建造者模式的好處就是使得建造代碼與表示代碼分離,因爲建造者隱藏了該產品是如何組裝的,因此若須要改變一個產品的內部表示,只須要在定義一個具體的建造者就能夠了。
建造者模式是在當建立複雜對象的算法應該獨立於該對象的組成部分以及他們的裝配方式時適用的模式。