六.创建型设计模式——Builder Pattern(建造者模式)

  • 定义

  将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建他们。用户不知道内部的具体构建细节。

  UML类图如下:

  

  其中的类或对象之间的关系为:

  1. Builder(抽象建造者):为创建一个Product对象的各个部件指定抽象接口。

  2. ConcreteBuilder(具体建造者):

    (1). 实现Builder接口,构造和装配产品的各个部件。

    (2). 定义并明确它所创建的表示。

    (3). 提供一个返回这个产品的接口。

  3. Director(指挥者):构建一个使用Builder接口的对象。

  4. Product(产品角色):

    (1). 被构建的复杂对象,具体建造者创建该产品的内部表示并定义它的装配过程。

    (2). 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

  典型应用的顺序图如下:

  

  为什么需要Director

  在这个模式中,Director类好像是一个多余的类,在应用中的作用好像不大。其实它的作用是明显的。第一,它隔离了客户及生产过程。第二,它负责控制产品的生成过程。比如你是客户,你要去买车子,你选好车型、颜色、内外饰等,交给Director,Director告诉你去某车间取车就可以。这样,其作用大家都能体会出来了吧?

  Builder模式与AbstractFactory模式的区别

  建造者模式(Builder)与抽象工厂模式(AbstractFactory)很相像,但是,Builder返回完整的一个产品,而AbstractFactory返回一系列有关系的产品;在抽象工厂模式中,客户采用AbstractFactory生成自己要用的对象,而在建造者模式中,客户指导Builder类如何去生成对象,或是如何和成一些类来构成建造类,侧重于一步步构造一个复杂对象,然后将结果返回。

  • 实例1——车间造车  

  车间装配车辆是分步骤完成的复杂装配过程,车行(VehicleBuilder)采用不同的车间装配出不同类型的车辆。其类图如下:

  

  

代码
//指挥者
class Shop
{
public void Construct(VehicleBuilder vehicleBuilder)
{
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWheels();
vehicleBuilder.BuildDoors();
}
}

//建造者
abstract class VehicleBuilder
{
protected Vehicle vehicle;
public Vehicle Vehicle
{
get{return vehicle;}
}
//装配框架
abstract public void BuildFrame();
//装配发动机
abstract public void BuildEngine();
//装配轮子
abstract public void BuildWheels();
//装配车门
abstract public void BuildDoors();
}
//具体建造者——摩托车车间
class MotorCycleBuilder : VehicleBuilder
{
public override void BuildFrame()
{
vehicle
= new Vehicle("摩托车");
vehicle[
"frame"] = "MotorCycle Frane";
}
public override void BuildEngine()
{
vehicle[
"engine"] = "500 cc";
}
public override void BuildWheels()
{
vehicle[
"wheels"] = "2";
}
public override void BuildDoors()
{
vehicle[
"doors"] = "0";
}
}
//具体建造者——轿车车间
class CarBuilder : VehicleBuilder
{
public override void BuildFrame()
{
vehicle
= new Vehicle("轿车");
vehicle[
"frame"] = "Car Frane";
}
public override void BuildEngine()
{
vehicle[
"engine"] = "2500 cc";
}
public override void BuildWheels()
{
vehicle[
"wheels"] = "4";
}
public override void BuildDoors()
{
vehicle[
"doors"] = "4";
}
}
//具体建造者——轿车车间
class ScooterBuilder : VehicleBuilder
{
public override void BuildFrame()
{
vehicle
= new Vehicle("单轮滑行车");
vehicle[
"frame"] = "Scooter Frane";
}
public override void BuildEngine()
{
vehicle[
"engine"] = "none";
}
public override void BuildWheels()
{
vehicle[
"wheels"] = "2";
}
public override void BuildDoors()
{
vehicle[
"doors"] = "0";
}
}

//车辆产品类
class Vehicle
{
private string type;
private Hashtable parts = new Hashtable();
//构造函数
public Vehicle(string type)
{
this.type = type;
}
public object this[string key]
{
get { return parts[key]; }
set { parts[key] = value; }
}
public void Show()
{
Console.WriteLine(
"\n----------------------------");
Console.WriteLine(
"车辆类型:" + type);
Console.WriteLine(
"框架:" + parts["frame"]);
Console.WriteLine(
"发动机:" + parts["engine"]);
Console.WriteLine(
"#轮子数:" + parts["wheels"]);
Console.WriteLine(
"#车门数:" + parts["doors"]);
}
}

//客户应用测试
class Client
{
[STAThread]
static void Main(string[] args)
{
//创建车间及指挥者
Shop shop = new Shop();
VehicleBuilder b1
= new ScooterBuilder();
VehicleBuilder b2
= new CarBuilder();
VehicleBuilder b3
= new MotorCycleBuilder();
//装配并显示车辆
shop.Construct(b1);
b1.Vehicle.Show();
shop.Construct(b2);
b2.Vehicle.Show();
shop.Construct(b3);
b3.Vehicle.Show();
Console.Read();
}
}
  • 实例2——建造房屋 

  建造房屋时,客户通过调用BuildHouse方法请求Director去创建房子。传递一个布尔参数mblnBackyard,如果mblnBackyard的值是false,Director创造一个Apartment(公寓)对象;如果mblnBackyard的值是true,Director创造一个SingleFamilyHome(家庭)对象。两种情况下,Director都返回House接口。

  Director做了复杂的建设房屋的工作,客户仅仅取得Director返回的House接口,而不用知道如何建造房屋、房间、后院等。类图如下:

  

  

代码
//定义iHouse接口
public interface iHouse
{
bool GetBackyard();
long NoOfRooms();
string Description();
}
//定义Apartment(公寓),有3间房间,没有后院
public class Apartment : iHouse
{
private bool mblnBackyard;
private ArrayList rooms;
public Apartment()
{
Room room
= new Room();
rooms
= new ArrayList();
room.RoomName
= "Master Room";
rooms.Add(room);
room
= new Room();
room.RoomName
= "Second Room";
rooms.Add(room);
room
= new Room();
room.RoomName
= "Living Room";
rooms.Add(room);
mblnBackyard
= false;
}
public bool GetBackyard()
{
return mblnBackyard;
}
public long NoOfRooms()
{
return rooms.Count;
}
public string Description()
{
string strDescription;
strDescription
= "这是一间公寓,有" + rooms.Count + "间房间\n";
strDescription
+= "这间公寓没有后院";
for (int i = 1; i <= rooms.Count; i++)
{
strDescription
+= "\n房间" + i + "\t" + ((Room)rooms[i - 1]).RoomName;
}
return strDescription;
}
}
//定义SingleFamilyHome(别墅),有5间房间,配有后院
public class SingleFamilyHome : iHouse
{
private bool mblnBackyard;
private ArrayList rooms;
public SingleFamilyHome()
{
Room room
= new Room();
rooms
= new ArrayList();
room.RoomName
= "Master BedRoom";
rooms.Add(room);
room
= new Room();
room.RoomName
= "Second BedRoom";
rooms.Add(room);
room
= new Room();
room.RoomName
= "Thrid BedRoom";
rooms.Add(room);
room
= new Room();
room.RoomName
= "Living BedRoom";
rooms.Add(room);
room
= new Room();
room.RoomName
= "Guest BedRoom";
rooms.Add(room);
mblnBackyard
= true;
}
public bool GetBackyard()
{
return mblnBackyard;
}
public long NoOfRooms()
{
return rooms.Count;
}
public string Description()
{
string strDescription;
strDescription
= "这是一间别墅,有" + rooms.Count + "间房间\n";
strDescription
+= "这间别墅有后院";
for (int i = 1; i <= rooms.Count; i++)
{
strDescription
+= "\n房间" + i + "\t" + ((Room)rooms[i - 1]).RoomName;
}
return strDescription;
}
}

//房间类
public class Room
{
public string RoomName;
}

//Director根据客户传入的mblnBackyard参数的值,创建不同的House
public class Director
{
public iHouse BuildHouse(bool mblnBackyard)
{
if (mblnBackyard)
return new SingleFamilyHome();
else
return new Apartment();
}
}


//客户应用测试
class Client
{
[STAThread]
static void Main(string[] args)
{
Director director
= new Director();
iHouse ihouse
= director.BuildHouse(false);
Console.WriteLine(ihouse.Description());
ihouse
= director.BuildHouse(true);
Console.WriteLine(ihouse.Description());
Console.Read();
}
}
  • 优势和缺陷

  建造者模式将一个复杂对象的生成责任作了很好的分配。它把构造过程放在指挥者的方法中,把装配过程放到具体建造者类中。建造者模式的产品之间都有共通点,但有时候,产品之间的差异性很大,这就需要借助工厂方法模式或抽象工厂模式。另外,如果产品的内部变化复杂,Builder的每一个子类都需要对应到不同的产品去做构建的动作、方法,这就需要定义很多个具体建造类来实现这种变化。

  • 应用情景

  下面的情景很适合应用建造者模式:

  1. 创建复杂对象的算法是独立于它的组成部件及装配过程。

  2. 构造的过程允许构造对象有不同的表现。

posted on 2010-10-23 00:08  tLEE  阅读(753)  评论(0编辑  收藏  举报

导航