一、 定义
建造者模式(Builder):将一个复杂对象的构建与它的表示分离,似的同样的构建过程可以创建不同的表示。
自己的理解:这个模式适用的场景是要建一些复杂的对象,但是这些对象建造的过程即构建大体一致,只是最后呈现出的结果不一样而已。举个例子,我要盖一个房子,不管什么类型的房子,盖的时候都要打地基,盖出框架,装上门,窗等,有一个共同的工序。但是最终展示出来的到底是几层,有几个门,门的材料,大小等这个是可变的。将客户端与创建过程分离,用户不用知道房子是怎么建的,只需清楚自己要什么样的房子,然后把条件输入就等着房子盖好就OK了。符合开闭原则。这样我们可以把不变的部分和变化的部分分离,都抽象出类,这样提高软件的扩展性,维护性和复用性。
二、 UML类图
Builder(创建者):提供创建产品的一个接口
ConcreteBuilder(具体创建者):实现Builder接口以构造和装配产品的各部件。
Director(指挥者):构造一个使用Builder接口的对象。
三、代码示例(创建小人)
<span style="font-family:KaiTi_GB2312;">namespace 建造者模式
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnDrawPerson_Click(object sender, EventArgs e)
{
Pen p = new Pen(Color.Blue );
PersonThinBuilder ptb = new PersonThinBuilder(picShow.CreateGraphics(), p);
PersonDirector pdThin = new PersonDirector(ptb);
pdThin.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, 70, 50, 90, 100);
}
public override void BuildArmRight()
{
g.DrawLine(p, 70, 100, 85, 150);
}
public override void BuildLegLeft()
{
g.DrawLine(p, 60, 100, 45, 150);
}
public override void BuildLegRight()
{
g.DrawLine(p, 70, 100, 85, 150);
}
}
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();
}
}
}
</span>
四、 适用环境和优缺点
适用环境:产品有差异但是建造过程大致一样
优点:
1、建造时抽象出了建造者接口和具体的建造者类。如果要修改建造过程可以只改Builder接口,如果需要增加新的产品,只需抽象出新的ConcreteBuilder类就行了,保证了软件的可维护性和可扩展性。
2、使用Director(指挥者)使得客户端不知道产品到底是怎么建造的,实现了构建和表示的分离,体现了开闭原则。
缺点:
1、如果产品之间的差异很大,共同的组成部分或共同的建造过程不明显就不能使用该模式 。
2、如果产品内部变化大,可能需要增加更多的ConcreteBuilder类来实现,这就会是系统变的复杂。
五、感悟
现在又一个疑惑:机房收费系统中涉及到了好多组合查询,一开始想他们的建造过程大致一样,都是判断第一行选中了没,第二行选中了没等等呢过,只是有些细微的差别,能不能用建造者模式?后来一想记得好几个窗体都是三个查询组合到一起,好像连命名都一样,那为什么不用原型模式呢,直接复制再稍微改改不就好了吗?后来再一想复制的基本上都是一样的,我第一个要是三个查询组合,之后都是三个,我要是再加第四个,第五的时候就不好更改了,不符合开闭原则,pass掉。用建造者模式的话可以把创建一个查询写到建造者接口中,想要几个组合查询就写几个具体建造者类呗。
只是瞎想想,具体指挥者的类写什么我还不太清楚,到底这个模式合不合适等重构的时候再细想吧。