设计模式之Builder生成器模式

 
意图intent:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用性:
  • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
  • 当构造过程必须允许被构造的对象有不同的表示时。
Definition:Separate the construction of a complex object from its representation so that the same construction process can create different representations.
 
Participants
    The classes and/or objects participating in this pattern are:
  • Builder  (VehicleBuilder)
    • specifies an abstract interface for creating parts of a Product object
  • ConcreteBuilder  (MotorCycleBuilder, CarBuilder, ScooterBuilder)
    • constructs and assembles parts of the product by implementing the Builder interface
    • defines and keeps track of the representation it creates
    • provides an interface for retrieving the product
  • Director  (Shop)
    • constructs an object using the Builder interface
  • Product  (Vehicle)
    • represents the complex object under construction. ConcreteBuilder builds the product's internal representation and defines the process by which it's assembled
    • includes classes that define the constituent parts, including interfaces for assembling the parts into the final result
 
This real-world code demonstates the Builder pattern in which different vehicles are assembled in a step-by-step fashion. The Shop uses VehicleBuilders to construct a variety of Vehicles in a series of sequential steps.
// Builder pattern -- Real World example (c#)


using System;
using System.Collections;

namespace DoFactory.GangOfFour.Builder.RealWorld
{
  // MainApp test application

  public class MainApp
  {
    public static void Main()
    {
      // Create shop with vehicle builders
      Shop shop = new Shop();
      VehicleBuilder b1 = new ScooterBuilder();
      VehicleBuilder b2 = new CarBuilder();
      VehicleBuilder b3 = new MotorCycleBuilder();

      // Construct and display vehicles
      shop.Construct(b1);
      b1.Vehicle.Show();

      shop.Construct(b2);
      b2.Vehicle.Show();

      shop.Construct(b3);
      b3.Vehicle.Show();

      // Wait for user
      Console.Read();
    }
  }

  // "Director"

  class Shop
  {
    // Builder uses a complex series of steps
    public void Construct(VehicleBuilder vehicleBuilder)
    {
      vehicleBuilder.BuildFrame();
      vehicleBuilder.BuildEngine();
      vehicleBuilder.BuildWheels();
      vehicleBuilder.BuildDoors();
    }
  }

  // "Builder"

  abstract class VehicleBuilder
  {
    protected Vehicle vehicle;

    // Property
    public Vehicle Vehicle
    {
      get{ return vehicle; }
    }

    public abstract void BuildFrame();
    public abstract void BuildEngine();
    public abstract void BuildWheels();
    public abstract void BuildDoors();
  }

  // "ConcreteBuilder1"

  class MotorCycleBuilder : VehicleBuilder
  {
    public override void BuildFrame()
    {
      vehicle = new Vehicle("MotorCycle");
      vehicle["frame"] = "MotorCycle Frame";
    }

    public override void BuildEngine()
    {
      vehicle["engine"] = "500 cc";
    }

    public override void BuildWheels()
    {
      vehicle["wheels"] = "2";
    }

    public override void BuildDoors()
    {
      vehicle["doors"] = "0";
    }
  }

  // "ConcreteBuilder2"

  class CarBuilder : VehicleBuilder
  {
    public override void BuildFrame()
    {
      vehicle = new Vehicle("Car");
      vehicle["frame"] = "Car Frame";
    }

    public override void BuildEngine()
    {
      vehicle["engine"] = "2500 cc";
    }

    public override void BuildWheels()
    {
      vehicle["wheels"] = "4";
    }

    public override void BuildDoors()
    {
      vehicle["doors"] = "4";
    }
  }

  // "ConcreteBuilder3"

  class ScooterBuilder : VehicleBuilder
  {
    public override void BuildFrame()
    {
      vehicle = new Vehicle("Scooter");
      vehicle["frame"] = "Scooter Frame";
    }

    public override void BuildEngine()
    {
      vehicle["engine"] = "50 cc";
    }

    public override void BuildWheels()
    {
      vehicle["wheels"] = "2";
    }

    public override void BuildDoors()
    {
      vehicle["doors"] = "0";
    }
  }

  // "Product"

  class Vehicle
  {
    private string type;
    private Hashtable parts = new Hashtable();

    // Constructor
    public Vehicle(string type)
    {
      this.type = type;
    }

    // Indexer (i.e. smart array)
    public object this[string key]
    {
      get{ return parts[key]; }
      set{ parts[key] = value; }
    }

    public void Show()
    {
      Console.WriteLine("/n---------------------------");
      Console.WriteLine("Vehicle Type: {0}", type);
      Console.WriteLine(" Frame : {0}", parts["frame"]);
      Console.WriteLine(" Engine : {0}", parts["engine"]);
      Console.WriteLine(" #Wheels: {0}", parts["wheels"]);
      Console.WriteLine(" #Doors : {0}", parts["doors"]);
    }
  }
}

Output
---------------------------
Vehicle Type: Scooter
 Frame  : Scooter Frame
 Engine : none
 #Wheels: 2
 #Doors : 0

---------------------------
Vehicle Type: Car
 Frame  : Car Frame
 Engine : 2500 cc
 #Wheels: 4
 #Doors : 4

---------------------------
Vehicle Type: MotorCycle
 Frame  : MotorCycle Frame
 Engine : 500 cc
 #Wheels: 2
 #Doors : 0
 
 
不过由于俺缺少经验,个人感觉Builder模式用处不大阿。它的主要作用就是把生成一个复杂的product分成了几个部分,如BuildA, BuildB, …,然后通过Director来统一construct。如果要构建的product不是很复杂的话,我们完全可以直接在concrete product里面build了,而不用分成part1,part2,…了。当然了,即使分成了好几个部分,我们还是可以直接在concrete product里面直接build的,甚至在getResult里面生成。我想,builder模式里面除了把复杂product分成好几个部分的优点外,另外的就是通过Director来统一构建步骤。因为concrete products都是来interface product的,所以其构建步骤是一定的。此时,如果我们有很多同样的东西要构建的话,就会非常方便了。
看了这个模式,思考了一会,还是感觉用处不大阿。因为我觉得在实际项目中,很少有人会把一个product分成那么多的part的吧?而且还需要有很多同样类型的产品,而且还要求他们要有同样的构建步骤。另外,我觉得这里的扩展性也不是很强啊。如果我产品的part改变了呢?少了一个part呢?少了一个part的话,我可以简单的在concrete product里面使用空函数。但是如果多了一个part呢?难道要我把这一part放在另一个part里面实现?那样的话不久破坏了原有的设计了吗?而且,后来的product大多是都会多一个part吧。云云。
先写到这里吧,等俺把23个模式都学好了再好好得总结总结,再深入地理解一下。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值