比如,建房子,一般顺序是看地段,设计蓝图,打地基,建造框架,完成建造。
一般来说的话,建房子的步骤基本上就是上面的这几个,也就是说基本的建造房子的顺序基本上是确定的,
但是对于其中的每一项都是有千万种变化的,比如建造框架,就可以建造成方的,圆的,半圆的,半方的等等,
上面说明的就是把房子看做一个对象,那么建造这个对象呢,需要在内部构建诸如看地段,设计蓝图等等部件,
而这些部件都是有千变万化的,所以我们便可以使用建造者模式来建造房子,
我在 AbstractBuilder 中建立基本的建造房子的对外接口,比如有看地段,设计蓝图等,
然后我如果需要建造一个方的房子的话,我只需要一个 ConcreteBuilder ,
然后使其继承自 AbstractBuilder ,并且按建方房子的方式重写在 AbstractBuilder 中定义的接口。
这样便可以实现建造一个方房子。
而如果我又需要建造一个圆房子,那么我只需要添加一个 ConcreteBuilder ,
并且让其继承自 AbstractBuilder ,并且按建造圆房子的方式重写 AbstractBuilder 中定义的接口就 OK 了。
从上面的这个建房子的例子中也可以看出建造者模式的一些优点,
建造者模式让建造代码和表示代码分离,由于建造者隐藏了该产品是如何组装的(由指挥者完成的组装,客户端根本就不知道),
所以需要改变一个产品的内部表示时,只需要添加一个具体建造者类就 OK 了。
HouseBuilder:
BlockHouseBuilder :
namespace BuilderHouse
{
/// <summary>
/// 圆木小屋的建造接口
/// </summary>
public class BlockHouseBuilder : HouseBuilder
{
private House house = new House();
public override void FindGroundsill()
{
house.AddPart("建造圆木小屋--看地段");
}
public override void DesignBluePrint()
{
house.AddPart("建造圆木小屋--设计蓝图");
}
public override void BuildFoundation()
{
house.AddPart("建造圆木小屋--打地基");
}
public override void BuildFrame()
{
house.AddPart("建造圆木小屋--建造框架");
}
public override void FinishBuild()
{
house.AddPart("建造圆木小屋--完成建造");
}
public override House GetHouse()
{
return house;
}
}
}
LogCabinBuilder :
House:
using System;
using System.Collections.Generic;
namespace BuilderHouse
{
public class House
{
private IList<string> parts = new List<string>();
public void AddPart(string part)
{
this.parts.Add(part);
}
public void ShowHouse()
{
foreach (string str in parts)
{
Console.WriteLine(str);
}
}
}
}
Director:
namespace BuilderHouse
{
public class Director
{
public void BuildHouse(HouseBuilder builder)
{
//先看地段
builder.FindGroundsill();
//再设计蓝图
builder.DesignBluePrint();
//再打地基
builder.BuildFoundation();
//再建造框架
builder.BuildFrame();
//最后就是完成建造了
builder.FinishBuild();
}
}
}
客户端代码:
using System;
using BuilderHouse;
namespace BuilderHouseTest
{
class Program
{
static void Main(string[] args)
{
//先实例化一个指挥者
Director director = new Director();
//建造圆木小屋
Console.WriteLine("\n建造圆木小屋\n");
HouseBuilder blockHouse = new BlockHouseBuilder();
//通过指挥者来建造圆木小屋
director.BuildHouse(blockHouse);
//下面这步骤就无关紧要了,纯粹是为了显示而已
blockHouse.GetHouse().ShowHouse();
//建造小巧木屋
Console.WriteLine("\n建造小巧木屋\n");
HouseBuilder logCabin = new LogCabinBuilder();
director.BuildHouse(logCabin);
logCabin.GetHouse().ShowHouse();
Console.ReadKey();
}
}
}
上面的代码便完成了建房子这个例子了,
为了清楚的明白建造者模式,下面我在考虑如果我要建造一个别墅 Villadom ,
那么应该如何做呢,很简单,加下面一个类,
namespace BuilderHouse
{
/// <summary>
/// 建造富豪别墅
/// </summary>
public class Villadom : HouseBuilder
{
private House house = new House();
public override void FindGroundsill()
{
this.house.AddPart("建造富豪别墅--看地段");
}
public override void DesignBluePrint()
{
this.house.AddPart("建造富豪别墅--设计蓝图");
}
public override void BuildFoundation()
{
this.house.AddPart("建造富豪别墅--打地基");
}
public override void BuildFrame()
{
this.house.AddPart("建造富豪别墅--建造框架");
}
public override void FinishBuild()
{
this.house.AddPart("建造富豪别墅--完成建造");
}
public override House GetHouse()
{
return house;
}
}
}
然后就可以在客户端通过指挥者来建造别墅了,这里便体现出了建造者模式的优势。
namespace BuilderHouse
{
/// <summary>
/// 建造小巧木屋
/// </summary>
public class LogCabinBuilder : HouseBuilder
{
private House house = new House();
public override void FindGroundsill()
{
this.house.AddPart("建造小巧木屋--看地段");
}
public override void DesignBluePrint()
{
this.house.AddPart("建造小巧木屋--设计蓝图");
}
public override void BuildFoundation()
{
this.house.AddPart("建造小巧木屋--打地基");
}
public override void BuildFrame()
{
this.house.AddPart("建造小巧木屋--建造框架");
}
public override void FinishBuild()
{
this.house.AddPart("建造小巧木屋--完成建造");
}
public override House GetHouse()
{
return house;
}
}
}
namespace BuilderHouse
{
public abstract class HouseBuilder
{
//看地段
public abstract void FindGroundsill();
//设计蓝图
public abstract void DesignBluePrint();
//打地基
public abstract void BuildFoundation();
//建造框架
public abstract void BuildFrame();
//完成建造
public abstract void FinishBuild();
//返回建造好的房子
public abstract House GetHouse();
}
}