您的位置:首页 > 产品设计 > UI/UE

Design Pattern - Creational Patterns - Builder Pattern

2016-06-25 19:11 645 查看
2007


Section 3, Chapter 2
Builder Pattern

Concept

Builders usually deal with construction of complex objects or objects whose construction, initialization, and configuration spans more than one process and whose creational code is complex.

Use

Builders are used to prevent duplication of creational code, and act as a central repository for the creational code involved. So a builder might be used when you have several processes that aid in the creation of an object,
and the object's creation or initialization is dependent on each of these processes.

Builders are useful for any creational methods spanning a number of operations. They are also useful for maintaining the order of the operations in creating classes. Using inheritance, we can make sure builders can provide us
polymorphic processing of creational logic and can change this logic across inherited implementations. Using builders we can create a class, initialize its state, and maintain the order of operations for how the class gets created and configured. We can use
builders in a variety of ways with factories and provide either added functionality or enhanced usability in their association.

Design

Builder: responsible for defining and producing individual parts of a whole class or product. It holds a number of processes needed to build, initialize, and configure the product class.

Director: the class that helps the builder to put all the methods together in a cohesive and consequential manner.

Product: the class that is produced from the builder-director relationship.



Illustration



We need a way to make sure we perform the same order of operations for any builder. For this purpose we create a Director class that has a method that receives as an input parameter the abstract HouseBuilder class. Inside the
director class's Construct() method we identify each operation and its order of execution. This ensures that no matter which House class we want to create we always configure them in a uniform manner.

public abstract class HouseBuilder
{
public abstract House CreateHouse();
public abstract Floor CreateFloor();
public abstract Wall CreateWall();
public abstract Roof CreateRoof();
}

class DuplexBuilder : HouseBuilder
{
public override House CreateHouse()
{
return new Duplex();
}
public override Floor CreateFloor()
{
return new CementFloor();
}
public override Wall CreateWall()
{
return new CementBlockWall();
}
public override Roof CreateRoof()
{
return new ShingledRoof();
}
}

class HouseDirector
{
public House Construct(HouseBuilder builder)
{
House house = builder.CreateHouse();
house.Floor = builder.CreateFloor();
house.EastWall = builder.CreateWall();
house.WestWall = builder.CreateWall();
house.SouthWall = builder.CreateWall();
house.NorthWall = builder.CreateWall();
house.Roof = builder.CreateRoof();
return house;
}
}

HouseDirector director = new HouseDirector();
House duplex = director.Construct(new DuplexBuilder());
House hud = director.Construct(new HUDBuilder());


With Factory pattern:



public abstract class Suit
{
Tie _tie;
Belt _belt;
public Tie Tie
{
get{return _tie;}
set{_tie = value;}
}
public Belt Belt
{
get{return _belt;}
set{_belt = value;}
}
}

public class Armani : Suit
{
CuffLinks _cuffLinks;
public CuffLinks CuffLinks
{
get{return _cuffLinks;}
set{_cuffLinks = value;}
}
}

public class StripedBusinessSuit : Suit {}

public class PlaidBusinessSuit : Suit {}

public class GolfSuit : Suit {}


public abstract class Builder
{
public abstract void CreateEnsemble(ref Suit suit);
}

public class GolfSuitBuilder : Builder
{
public override void CreateEnsemble(ref Suit suit)
{
GolfSuit aSuit = (GolfSuit)suit;
aSuit.Tie = null;
aSuit.Belt = new LeatherBelt();
}
}

public class ArmaniBuilder : Builder
{
public override void CreateEnsemble(ref Suit suit)
{
Armani aSuit = (Armani)suit;
aSuit.Tie = new StripedTie();
aSuit.Belt = new LeatherBelt();
aSuit.CuffLinks = new GoldCuffLinks();
//extended attribute for Armani
}
}


public sealed class SuitFactory
{
...
public void Register(SuitType suitType, Type type, Builder builder)
{
_registered.Add(suitType, type);
_builders.Add(suitType, builder);
}
public Suit CreateSuit(SuitType suitType)
{
if(_loaded[suitType] == null)
Load();
Suit suit = (Suit)_loaded[suitType];

// overwrite the suit object if it has its specific builder
if(_builders[suitType] != null)
{
Builder builder = (Builder)_builders[suitType];
builder.CreateEnsemble(ref suit);
}

return suit;
}
}


SuitFactory factory = new SuitFactory();
factory.Register(SuitType.Armani, typeof(Armani), new ArmaniBuilder());
factory.Register(SuitType.GolfSuit, typeof(GolfSuit), new GolfSuitBuilder());
factory.Register(SuitType.PlaidBusinessSuit, typeof(PlaidBusinessSuit), null);
factory.Register(SuitType.StripedBusinessSuit, typeof(StripedBusinessSuit), null);


Suit suit = factory.CreateSuit(SuitType.Armani);
suit = factory.CreateSuit(SuitType.GolfSuit);
suit = factory.CreateSuit(SuitType.PlaidBusinessSuit);
suit = factory.CreateSuit(SuitType.StripedBusinessSuit);


Note: The implementation of load() in factory class is unclear.
December 2007


Section 2, Chapter 6
Design



IBuilder: An interface defining what can be built

Director: A sequence of operations that can be followed to create a Product

Builder: A class that is called by a Director to make Product parts

Product: The object under construction, by parts

The Builder pattern is based on Directors and Builders.

Any number of Builder classes can conform to an IBuilder interface, and they can be called by a director to produce a product according to specification.

Different builders can supply different parts.

There can be several Directors and Builders.

The client calls Construct for a particular Director with a particular Builder. The Director has an individual way of putting together parts on offer from the Builder interface. The Product maintains a running list of the parts
as they are created, and this list is the result of the construction process.

Implementation

using System;
using System.Collections.Generic;

// Builder Pattern Judith Bishop November 2007
// Simple theory code with one director and two builders
class Director {
// Build a Product from several parts
public void Construct(IBuilder builder) {
builder.BuildPartA();
builder.BuildPartB();
builder.BuildPartB();
}
}

interface IBuilder {
void BuildPartA();
void BuildPartB();
Product GetResult();
}

class Builder1: IBuilder {
private Product product = new Product();
public void BuildPartA() {
product.Add("PartA ");
}
public void BuildPartB() {
product.Add("PartB ");
}
public Product GetResult() {
return product;
}
}

class Builder2: IBuilder {
private Product product = new Product();
public void BuildPartA() {
product.Add("PartX ");
}
public void BuildPartB() {
product.Add("PartY ");
}
public Product GetResult() {
return product;
}
}

class Product {
List < string > parts = new List < string > ();
public void Add(string part) {
parts.Add(part);
}
public void Display() {
Console.WriteLine("\nProduct Parts -------");
foreach(string part in parts)
Console.Write(part);
Console.WriteLine();
}
}

public class Client {
public static void Main() {
// Create one director and two builders
Director director = new Director();
IBuilder b1 = new Builder1();
IBuilder b2 = new Builder2();
// Construct two products
director.Construct(b1);
Product p1 = b1.GetResult();
p1.Display();
director.Construct(b2);
Product p2 = b2.GetResult();
p2.Display();
}
}


using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace BuilderPattern {
// Builder Pattern D-J Miller and Judith Bishop Sept 2007
// Abstract Factory : Builder Implementation
interface IBuilder<Brand> where Brand: IBrand {
IBag CreateBag();
}

// Abstract Factory now the Builder
class Builder<Brand> :IBuilder<Brand> where Brand: IBrand,
new() {
Brand myBrand;
public Builder() {
myBrand = new Brand();
}
public IBag CreateBag() {
return myBrand.CreateBag();
}
}

// Product 1
interface IBag {
string Properties {
get;
set;
}
}

// Concrete Product 1
class Bag: IBag {
public string Properties {
get;
set;
}
}

// Directors
interface IBrand {
IBag CreateBag();
}

class Gucci: IBrand {
public IBag CreateBag() {
Bag b = new Bag();
Program.DoWork("Cut Leather", 250);
Program.DoWork("Sew leather", 1000);
b.Properties += "Leather";
Program.DoWork("Create Lining", 500);
Program.DoWork("Attach Lining", 1000);
b.Properties += " lined";
Program.DoWork("Add Label", 250);
b.Properties += " with label";
return b;
}
}

class Poochy: IBrand {
public IBag CreateBag() {
Bag b = new Bag();
Program.DoWork("Hire cheap labour", 200);
Program.DoWork("Cut Plastic", 125);
Program.DoWork("Sew Plastic", 500);
b.Properties += "Plastic";
Program.DoWork("Add Label", 100);
b.Properties += " with label";
return b;
}
}

class Client <Brand> where Brand: IBrand,
new() {
public void ClientMain() //IFactory<Brand> factory) {
IBuilder<Brand> factory = new Builder<Brand>();
DateTime date = DateTime.Now;
Console.WriteLine("I want to buy a bag!");
IBag bag = factory.CreateBag();
Console.WriteLine("I got my Bag which took " + DateTime.Now.Subtract(date).TotalSeconds * 5 + " days");
Console.WriteLine(" with the following properties " + bag.Properties + "\n");
}
}

static class Program {
static void Main() {
// Call Client twice
new Client<Poochy>().ClientMain();
new Client<Gucci>().ClientMain();
}
public static void DoWork(string workitem, int time) {
Console.Write("" + workitem + ": 0%");
Thread.Sleep(time);
Console.Write("....25%");
Thread.Sleep(time);
Console.Write("....50%");
Thread.Sleep(time);
Console.WriteLine("....100%");
}
}


where

new() {...}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息