意图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
|
不过由于俺缺少经验,个人感觉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个模式都学好了再好好得总结总结,再深入地理解一下。