书城计算机大话设计模式
11030400000106

第106章 7 汽车制造

大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方法――这并没有什么本质的区别。”