六.创建型设计模式——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. 构造的过程允许构造对象有不同的表现。

转载于:https://www.cnblogs.com/vrliym/archive/2010/10/23/1858798.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值