建造者模式(Builder),将一个复制对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式的UML图:
Builder是为创建一个Product对象的各个部件指定的抽象接口。
ConcreteBuilder是具体的建造者,实现Builder接口,构造和装备各个部件。
Product是产品角色,也就是具体的产品。
Director是指挥者,它是构建一个使用Builder接口的对象。
以下给出建造者模式的基本代码结构:
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(); } } }
生成结果如下图所示:
建造者模式使用注意点:共同要有的东西,例如头,身体,左手,右手,左脚,右脚等,提取出来设成抽象函数,这样就能够避免遗漏。同时,指挥者类放装配方法。控制创造过程。
建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要在定义一个具体的建造者就可以了。
建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时适用的模式。