大B:“就我刚才跟你讲的汽车制造作为例子。现在我再用图形和代码具体和你讲讲。”
namespace Builder
……{
//车身
public class Body
……{
private string name;
public string Name
……{
get……{return name;}
set……{name=value;}
}
public Body(string name)
……{
this。name=name;
}
}
//引擎
public class Engine
……{
private string name;
public string Name
……{
get……{return name;}
set……{name=value;}
}
public Engine(string name)
……{
this。name=name;
}
}
//车轮
public class Wheel
……{
private string name;
public string Name
……{
get……{return name;}
set……{name=value;}
}
public Wheel(string name)
……{
this。name=name;
}
}
//Benz汽车
public class Benz
{
private Body body;
private Engine engine;
private IList《Wheel》wheels;
public void AddBody(Body body)
{
this。body=body;
}
public void AddEngine(Engine engine)
{
this。engine=engine;
}
public void AddWheel(Wheel wheel)
{
if(wheels……null)
{
wheels=new List《Wheel》();
}
wheels。Add(wheel);
}
public void ShowMe()
{
if((this。body……null)||(this。engine……null)||(wheels……null))
{
Console。WriteLine(“This car has NOT been completed yet!”);
}
Else
{
Console。WriteLine(“This is a car with a” body。Name “and a” engine。Name );
Console。WriteLine(“This car contains” wheels。Count wheels:);
for(int i=0;i<wheels。Count;i )
{
Wheel wheel=wheels[i];
Console。WriteLine(wheel。Name);
}
}
}
}
//汽车制造厂抽象定义
public abstract class CarBuilder
{
public virtual void BuildBody(){;}//生产车身
public virtual void BuildEngine(){;}//生产引擎
public virtual void BuildWheel(string name){;}//生产车轮
}
//Benz汽车制造厂
public class BenzBuilder:CarBuilder
{
private Benz car;
public override void BuildBody()
{
car=new Car();
car。AddBody(new Body(“business car body”));
}
public override void BuildEngine()
{
car。AddEngine(new Engine(“benz engine”));
}
public override void BuildWheel(string name)
{
car。AddWheel(new Wheel(name));
}
//生产汽车,Benz汽车装配过程
public Benz GetCar()
{
//do something like to assemble body and engine together。
return car;
}
}
//汽车经销商
public class Producer
{
private CarBuilder builder;
public Producer(CarBuilder builder)
{
this。builder=builder;
}
public Car Construct()
{
builder。BuildBody();
builder。BuildEngine();
builder。BuildWheel(“front left”);
builder。BuildWheel(“front right”);
builder。BuildWheel(“back left”);
builder。BuildWheel(“back right”);
}
}
//客户端程序
public class Client
{
static void Main(string[]args)
{
BenzBuilder builder=new BenzCarBuilder();
Producer director=new Producer(builder);
director。Construct();
Benz car=builder。GetCar();
car。ShowMe();
}
}
}
小A:“这种类结构的设计,有什么好处呢?假设我们现在不想要刚才订的奔驰汽车了,而是想换成一辆路虎越野车怎么办?”
大B:“我们只需要告诉经销商,我们想改变汽车制造商就可以了!”
在上面的程序结构中,我们需要做的是:
1、定义一个路虎汽车及其制造商,实现制造车身、引擎、轮胎和组装的方法:
//Benz汽车
public class Benz
{
private Body body;
private Engine engine;
private IList《Wheel》wheels;
//……以下省略
}
public class LandRoverBuilder:CarBuilder
{
private LandRover car;
public override void BuildBody()
{
car=new Car();
car。AddBody(new Body(“business car body”));
}
public override void BuildEngine()
{
car。AddEngine(new Engine(“benz engine”));
}
public override void BuildWheel(string name)
{
car。AddWheel(new Wheel(name));
}
//生产汽车,LandRover汽车装配过程
public LandRover GetCar()
{
//do something like to assemble body and engine together。
return car;
}
}
2、修改客户端调用,把LandRoverBuilder提供给Producer:
LandRoverBuilder builder=new LandRoverCarBuilder();
Producer director=new Producer(builder);
director。Construct();
LandRover car=builder。GetCar();
car。ShowMe();
OK,你就得到一辆路虎了!这就是GoF说的“将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示”的含义!用同样的方式,你甚至可以得到一辆拖拉机!
大B:“让我们来稍微扩展一下思路,讨论一下扩展问题。我们注意到,在产品这个层次上,每个制造厂直接依赖于具体的汽车,如BenzBuilder生成Benz,在客户端使用时也必须依赖于具体的汽车制造厂BenzBuilder和具体汽车Benz,在抽象制造厂CarBuilder定义中也没有包含GetCar的定义。”
小A:“这是为什么呢?”
大B:“我们想想把Benz这个汽车这个产品也抽象化,定义为Car,具体汽车Benz和LandRover从Car继承,在CarBuider中定义GetCar方法依赖于抽象Car,从而在客户端也可以依赖于抽象。”
CarBuilder builder=new LandRoverCarBuilder();
roducer director=new Producer(builder);
irector。Construct();
Car car=builder。GetCar();
car。ShowMe();
大B:“这种做法没错,你把这个结构图画出来就可以看出,这就成了一个典型的工厂模式!实际上,工厂模式和生成器模式是经常引起混淆和困扰的模式,不过仔细体会两种模式的意图就可以发现,他们关注的重点不同。工厂模式的重点在于产品的系列化的生成问题:工厂方法模式解决一种产品细节差异,抽象工厂模式解决多种产品的系列化创建――这些产品可以很简单,也可以比较复杂。但是,这些产品都是整体创建的。而生成器模式关注的是复杂产品的创建细节――如何一步一步的完成复杂产品部件的创建和最后的组装过程。这个创建复杂产品的过程可以差距巨大,所装配出来的产品也可以差距巨大。比如,上面的CarBuilder定义的抽象过程,只要进行合适的扩充,Producer通过使用具体的生成器就可以生产出小汽车、越野车、赛车、拖拉机,甚至任何由车身、引擎和轮胎可以组合出来的产品!正是由于这些产品之间的差异如此巨大,因此无法在抽象的CarBuilder中定义一个GetProduct之类的抽象方法。我们再来看Producer这个类。它起到的是指导者的作用,指导生成器的使用方法,也就是利用生成器一步步建造出产品的过程。这个过程一般来说是固定的。通过修改Construct()方法,就可以改变产品的建造过程。当然,如果一个产品的建造过程也是系统的变化因素,当然也可以利用类似工厂模式的方法对Producer进行抽象和封装。最后我们来看看一下CarBuilder提供给Producer的方式。生成器模式的核心是给督导者一个生成器,但是具体方式并没有限定。可以像本例这样使用聚合的方式,也可以直接把CarBuilder作为参数提供给Construct方法――这并没有什么本质的区别。”