跳转到内容

建造者

25% developed
来自维基教科书,开放的书籍,为开放的世界

桥接 计算机科学设计模式
建造者
责任链

建造者模式对于避免一个类中出现大量的构造函数非常有用。让我们想象一个存储交通方式的类(例如,一个员工的交通方式)。以下是一个以 MetroLine 对象作为参数的构造函数

modeOfTransport(MetroLine)

现在我们需要一个构造函数,用于使用汽车、公交车或火车的人

new modeOfTransport(MetroLine)

new modeOfTransport()
new modeOfTransport(BusLine)

new modeOfTransport(Train)

对于其中一些,我们需要指定旅行津贴

new modeOfTransport(MetroLine)

new modeOfTransport(MetroLine, Integer)
new modeOfTransport()
new modeOfTransport(Integer)
new modeOfTransport(BusLine)
new modeOfTransport(BusLine, Integer)
new modeOfTransport(Train)

new modeOfTransport(Train, Integer)

我们有员工使用多种交通方式上班。然而,我们意识到构造函数列表现在已经变得很乱。每个新参数都会导致构造函数的指数级重复。如果某些参数具有相同的类型,它会变得非常混乱。解决这个问题的一个方法是先构建一个伪对象,然后通过调用其方法来填充它

new modeOfTransport(MetroLine)

modeOfTransport.setMetroLine(MetroLine)
modeOfTransport.setCarTravel()
modeOfTransport.setBusLine(BusLine)
modeOfTransport.setTrain(Train)

modeOfTransport.setTravelAllowance(Integer)

方法列表不再是指数级,但对象的状态可能不一致。更好的解决方案是将所有参数设置为另一个类的对象,一个预构造函数,然后将此对象传递给 ModeOfTransport 的构造函数

modeOfTransportPreConstructor.setMetroLine(MetroLine)

modeOfTransportPreConstructor.setCarTravel()
modeOfTransportPreConstructor.setBusLine(BusLine)
modeOfTransportPreConstructor.setTrain(Train)
modeOfTransportPreConstructor.setTravelAllowance(Integer)

new modeOfTransport(ModeOfTransportPreConstructor)

这个解决方案更好。我们只有一个有效的 ModeOfTransport 对象。但是,ModeOfTransport 构造函数可以使用半填充的预构造函数来调用。因此,预构造函数应该是一个建造者,应该有一个返回 ModeOfTransport 对象的方法。此方法仅在建造者被正确填充后才会返回对象,否则返回 null

modeOfTransportBuilder.setMetroLine(MetroLine)

modeOfTransportBuilder.setCarTravel()
modeOfTransportBuilder.setBusLine(BusLine)
modeOfTransportBuilder.setTrain(Train)
modeOfTransportBuilder.setTravelAllowance(Integer)

modeOfTransport := modeOfTransportBuilder.getResult()

因此,解决方案是使用建造者类。让我们在 UML 类图中查看代码的结构

Builder Structure
建造者结构
  • 建造者:用于创建对象(产品)的抽象接口。
  • 具体建造者:为建造者提供实现。它是一个能够构建其他对象的物体。构建并组装部件来构建物体。

建造者模式可用于包含扁平数据(html 代码、SQL 查询、X.509 证书等)的对象,即无法轻松编辑的数据。这种类型的数据无法一步步编辑,必须一次性编辑。构建此类对象的最佳方式是使用建造者类。

示例

在 Java 中,StringBufferStringBuilder 类遵循建造者设计模式。它们用于构建 String 对象。

成本

你可以很容易地决定是否使用它。最糟糕的情况是,模式是无用的。

创建

从一个具有公共构造函数的普通类开始,实现设计模式并不昂贵。你可以在代码旁边创建建造者类。然后,你将不得不删除现有的构造函数调用,以便改用建造者。重构几乎不是自动的。

维护

此设计模式只有很小的缺点。它可能会导致类和建造者结构之间出现小的冗余,但两个类通常具有不同的结构。但是,转换为抽象工厂很昂贵。

移除

重构几乎不是自动的。它应该手动完成。

建议

  • 在建造者类的名称中添加建造者一词,以便向其他开发人员表明使用了该模式。
  • 将你的建造者类构建为一个流畅的接口。这将增加模式的趣味性。
  • 如果目标类包含扁平数据,你的建造者类可以构建为一个组合,它实现了解释器模式。

实现

在 Java 中实现

制造汽车。

/**
 * Can have GPS, trip computer and a various number of seaters. Can be a city car, a sport car or a cabriolet.
 */
public class Car {
  /**
   * The description of the car.
   */
  private String description = null;

  /**
   * Construct and return the car.
   * @param aDescription The description of the car.
   */
  public Car(String aDescription) {
      description = aDescription;
    }
 
  /**
   * Print the car.
   * @return A flat representation.
   */
  public String toString() {
      return description;
    }
}
/**
 *
 */
public class CarBuilder {
  /**
   * Sport car.
   */
  private static final int SPORT_CAR = 1;

  /**
   * City car.
   */
  private static final int CITY_CAR = 2;

  /**
   * Cabriolet.
   */
  private static final int CABRIOLET = 3;

  /**
   * The type of the car.
   */
  private int carType;

  /**
   * True if the car has a trip computer.
   */
  private boolean hasTripComputer;

  /**
   * True if the car has a GPS.
   */
  private boolean hasGPS;

  /**
   * The number of seaters the car may have.
   */
  private int seaterNumber;

  /**
   * Construct and return the car.
   * @return a Car with the right options.
   */
  public Car getResult() {
      return new Car((carType == CITY_CAR) ? "A city car" : ((carType == SPORT_CAR) ? "A sport car" : "A cabriolet")
        + " with " + seaterNumber + " seaters"
        + (hasTripComputer ? " with a trip computer" : "")
        + (hasGPS ? " with a GPS" : "")
        + ".");
    }

  /**
   * Tell the builder the number of seaters.
   * @param number the number of seaters the car may have.
   */
  public void setSeaters(int number) {
      seaterNumber = number;
    }

  /**
   * Make the builder remember that the car is a city car.
   */
  public void setCityCar() {
      carType = CITY_CAR;
    }

  /**
   * Make the builder remember that the car is a cabriolet.
   */
  public void setCabriolet() {
      carType = CABRIOLET;
    }

  /**
   * Make the builder remember that the car is a sport car.
   */
  public void setSportCar() {
      carType = SPORT_CAR;
    }

  /**
   * Make the builder remember that the car has a trip computer.
   */
  public void setTripComputer() {
      hasTripComputer = true;
    }

  /**
   * Make the builder remember that the car has not a trip computer.
   */
  public void unsetTripComputer() {
      hasTripComputer = false;
    }

  /**
   * Make the builder remember that the car has a global positioning system.
   */
  public void setGPS() {
      hasGPS = true;
    }

  /**
   * Make the builder remember that the car has not a global positioning system.
   */
  public void unsetGPS() {
      hasGPS = false;
    }
}
/**
 * Construct a CarBuilder called carBuilder and build a car.
 */
public class Director {
  public static void main(String[] args) {
    CarBuilder carBuilder = new CarBuilder();
    carBuilder.setSeaters(2);
    carBuilder.setSportCar();
    carBuilder.setTripComputer();
    carBuilder.unsetGPS();
    Car car = carBuilder.getResult();

    System.out.println(car);
  }
}

它将产生

A sport car with 2 seaters with a trip computer.

制造披萨。

 /** "Product" */
class Pizza {
 private String dough = "";
 private String sauce = "";
 private String topping = "";

 public void setDough(final String dough) {
  this.dough = dough;
 }

 public void setSauce(final String sauce) {
  this.sauce = sauce;
 }

 public void setTopping(final String topping) {
  this.topping = topping;
 }
}
 /** "Abstract Builder" */
abstract class PizzaBuilder {
 protected Pizza pizza;

 public abstract void buildDough();
 public abstract void buildSauce();
 public abstract void buildTopping();

 public void createNewPizzaProduct() {
  this.pizza = new Pizza();
 }

 public Pizza getPizza() {
  return this.pizza;
 }
}
 /** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
 @Override public void buildDough() {
  this.pizza.setDough("cross");
 }

 @Override public void buildSauce() {
  this.pizza.setSauce("mild");
 }

 @Override public void buildTopping() {
  this.pizza.setTopping("ham+pineapple");
 }
}
 /** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
 @Override public void buildDough() {
  this.pizza.setDough("pan baked");
 }

 @Override public void buildSauce() {
  this.pizza.setSauce("hot");
 }

 @Override public void buildTopping() {
  this.pizza.setTopping("pepperoni+salami");
 }
}
 /** "Director" */
class Waiter {
 private PizzaBuilder pizzaBuilder;

 public void setPizzaBuilder(final PizzaBuilder pb) {
  this.pizzaBuilder = pb;
 }

 public Pizza getPizza() {
  return this.pizzaBuilder.getPizza();
 }

 public void constructPizza() {
  this.pizzaBuilder.createNewPizzaProduct();
  this.pizzaBuilder.buildDough();
  this.pizzaBuilder.buildSauce();
  this.pizzaBuilder.buildTopping();
 }
}
 /** A customer ordering a pizza. */
class BuilderExample {

 public static void main(final String[] args) {

  final Waiter waiter = new Waiter();

  final PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
  final PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

  waiter.setPizzaBuilder(hawaiianPizzaBuilder);
  waiter.constructPizza();

  final Pizza pizza = waiter.getPizza();

  waiter.setPizzaBuilder(spicyPizzaBuilder);
  waiter.constructPizza();

  final Pizza anotherPizza = waiter.getPizza();
 }
}
在 C# 中实现

在上面的例子中,Director 组装一个自行车实例,将构建委托给一个单独的建造者对象,该对象由 Client 提供给 Director。

/// <summary>
/// Represents a product created by the builder.
/// </summary>
public class Bicycle
{
    public Bicycle(string make, string model, string colour, int height)
    {
        Make = make;
        Model = model;
        Colour = colour;
        Height = height;
    }

    public string Make { get; set; }
    public string Model { get; set; }
    public int Height { get; set; }
    public string Colour { get; set; }
}

/// <summary>
/// The builder abstraction.
/// </summary>
public interface IBicycleBuilder
{
    Bicycle GetResult();

    string Colour { get; set; }
    int Height { get; set; }
}

/// <summary>
/// Concrete builder implementation.
/// </summary>
public class GTBuilder : IBicycleBuilder
{
    public Bicycle GetResult()
    {
        return Height == 29 ? new Bicycle("GT", "Avalanche", Colour, Height) : null;        
    }

    public string Colour { get; set; }
    public int Height { get; set; }
}

/// <summary>
/// The director.
/// </summary>
public class MountainBikeBuildDirector
{
    private IBicycleBuilder _builder;

    public MountainBikeBuildDirector(IBicycleBuilder builder) 
    {
        _builder = builder;
    }

    public void Construct()
    {
        _builder.Colour = "Red";
        _builder.Height = 29;
    }

    public Bicycle GetResult()
	{
		return this._builder.GetResult();
	}
}

public class Client
{
    public void DoSomethingWithBicycles()
    {
        var director = new MountainBikeBuildDirector(new GTBuilder());
        // Director controls the stepwise creation of product and returns the result.
        director.Construct();
        Bicycle myMountainBike = director.GetResult();
    }
}

另一个例子

using System;

namespace BuilderPattern
{
  // Builder - abstract interface for creating objects (the product, in this case)
  abstract class PizzaBuilder
  {
    protected Pizza pizza;

    public Pizza GetPizza()
    {
      return pizza;
    }

    public void CreateNewPizzaProduct()
    {
      pizza = new Pizza();
    }

    public abstract void BuildDough();
    public abstract void BuildSauce();
    public abstract void BuildTopping();
  }
  // Concrete Builder - provides implementation for Builder; an object able to construct other objects.
  // Constructs and assembles parts to build the objects
  class HawaiianPizzaBuilder : PizzaBuilder
  {
    public override void BuildDough()
    {
      pizza.dough = "cross";
    }

    public override void BuildSauce()
    {
      pizza.sauce = "mild";
    }

    public override void BuildTopping()
    {
      pizza.topping = "ham+pineapple";
    }
  }
  // Concrete Builder - provides implementation for Builder; an object able to construct other objects.
  // Constructs and assembles parts to build the objects
  class SpicyPizzaBuilder : PizzaBuilder
  {
    public override void BuildDough()
    {
      pizza.dough = "pan baked";
    }

    public override void BuildSauce()
    {
      pizza.sauce = "hot";
    }

    public override void BuildTopping()
    {
      pizza.topping = "pepperoni + salami";
    }
  }
 
  // Director - responsible for managing the correct sequence of object creation.
  // Receives a Concrete Builder as a parameter and executes the necessary operations on it.
  class Cook
  {
    private PizzaBuilder _pizzaBuilder;

    public void SetPizzaBuilder(PizzaBuilder pb)
    {
      _pizzaBuilder = pb;
    }

    public Pizza GetPizza()
    {
      return _pizzaBuilder.GetPizza();
    }

    public void ConstructPizza()
    {
      _pizzaBuilder.CreateNewPizzaProduct();
      _pizzaBuilder.BuildDough();
      _pizzaBuilder.BuildSauce();
      _pizzaBuilder.BuildTopping();
    }
  }

  // Product - The final object that will be created by the Director using Builder
  public class Pizza
  {
    public string dough = string.Empty;
    public string sauce = string.Empty;
    public string topping = string.Empty;
  }

  class Program
  {
    static void Main(string[] args)
    {
      PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
      Cook cook = new Cook();
      cook.SetPizzaBuilder(hawaiianPizzaBuilder);
      cook.ConstructPizza();
      // create the product
      Pizza hawaiian = cook.GetPizza();

      PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
      cook.SetPizzaBuilder(spicyPizzaBuilder);
      cook.ConstructPizza();
      // create another product
      Pizza spicy = cook.GetPizza();
    }
  }

}
在 C++ 中实现

此 C++11 实现基于书中的 C++98 之前的实现。

#include <iostream>

enum Direction {North, South, East, West};

class MapSite {
public:
  virtual void enter() = 0;
  virtual ~MapSite() = default;
};

class Room : public MapSite {
public:
  Room() :roomNumber(0) {}
  Room(int n) :roomNumber(n) {}
  void setSide(Direction d, MapSite* ms) {
    std::cout << "Room::setSide " << d << ' ' << ms << '\n';
  }
  virtual void enter() {}
  Room(const Room&) = delete; // rule of three
  Room& operator=(const Room&) = delete;
private:
  int roomNumber;
};

class Wall : public MapSite {
public:
  Wall() {}
  virtual void enter() {}
};

class Door : public MapSite {
public:
  Door(Room* r1 = nullptr, Room* r2 = nullptr)
    :room1(r1), room2(r2) {}
  virtual void enter() {}
  Door(const Door&) = delete; // rule of three
  Door& operator=(const Door&) = delete;
private:
  Room* room1;
  Room* room2;
};

class Maze {
public:
  void addRoom(Room* r) {
    std::cout << "Maze::addRoom " << r << '\n';
  }
  Room* roomNo(int) const {
    return nullptr;
  }
};

class MazeBuilder {
public:
  virtual ~MazeBuilder() = default;
  virtual void buildMaze() = 0;
  virtual void buildRoom(int room) = 0;
  virtual void buildDoor(int roomFrom, int roomTo) = 0;

  virtual Maze* getMaze() {
    return nullptr;
  }
protected:
  MazeBuilder() = default;
};

// If createMaze is passed an object that can create a new maze in its entirety using operations for adding rooms, doors, and walls to the maze it builds, then you can use inheritance to change parts of the maze or the way the maze is built. This is an example of the Builder (110) pattern.

class MazeGame {
public:
  Maze* createMaze(MazeBuilder& builder) {
    builder.buildMaze();
    builder.buildRoom(1);
    builder.buildRoom(2);
    builder.buildDoor(1, 2);
    return builder.getMaze();
  }
  Maze* CreateComplexMaze(MazeBuilder& builder) {
    builder.buildRoom(1);
    // ...
    builder.buildRoom(1001);
    return builder.getMaze();
  }
};

class StandardMazeBuilder : public MazeBuilder {
public:
  StandardMazeBuilder() :currentMaze(nullptr) {}
  virtual void buildMaze() {
    currentMaze = new Maze;
  }
  virtual void buildRoom(int n) {
    if (!currentMaze->roomNo(n)) {
      Room* room = new Room(n);
      currentMaze->addRoom(room);
      room->setSide(North, new Wall);
      room->setSide(South, new Wall);
      room->setSide(East, new Wall);
      room->setSide(West, new Wall);
    }
  }
  virtual void buildDoor(int n1, int n2) {
    Room* r1 = currentMaze->roomNo(n1);
    Room* r2 = currentMaze->roomNo(n2);
    Door* d = new Door(r1, r2);
    r1->setSide(commonWall(r1,r2), d);
    r2->setSide(commonWall(r2,r1), d);
  }
  virtual Maze* getMaze() {
    return currentMaze;
  }
  StandardMazeBuilder(const StandardMazeBuilder&) = delete; // rule of three
  StandardMazeBuilder& operator=(const StandardMazeBuilder&) = delete;
private:
  Direction commonWall(Room*, Room*) {
    return North;
  }
  Maze* currentMaze;
};

int main() {
  MazeGame game;
  StandardMazeBuilder builder;
  game.createMaze(builder);
  builder.getMaze();
}

程序输出类似

Maze::addRoom 0x2145ed0
Room::setSide 0 0x2146300
Room::setSide 1 0x2146320
Room::setSide 2 0x2146340
Room::setSide 3 0x2146360
Maze::addRoom 0x2146380
Room::setSide 0 0x21463a0
Room::setSide 1 0x21463c0
Room::setSide 2 0x21463e0
Room::setSide 3 0x2146400
Room::setSide 0 0x2146420
Room::setSide 0 0x2146420

另一个例子

#include <string>
#include <iostream>
using namespace std;
 
// "Product"
class Pizza {
public:
        void dough(const string& dough) {
                dough_ = dough;
        }
 
        void sauce(const string& sauce) {
                sauce_ = sauce;
        }
 
        void topping(const string& topping) {
                topping_ = topping;
        }
 
        void open() const {
                cout << "Pizza with " << dough_ << " dough, " << sauce_ << " sauce and "
                        << topping_ << " topping. Mmm." << endl;
        }
 
private:
        string dough_;
        string sauce_;
        string topping_;
};
 
// "Abstract Builder"
class PizzaBuilder {
public:
       // Chinmay Mandal : This default constructor may not be required here
        PizzaBuilder()
        {
           // Chinmay Mandal : Wrong syntax
           // pizza_ = new Pizza;
        }
        const Pizza& pizza() {
                return pizza_;
        }
 
        virtual void buildDough() = 0;
        virtual void buildSauce() = 0;
        virtual void buildTopping() = 0;
 
protected:
        Pizza pizza_;
};
 
class HawaiianPizzaBuilder : public PizzaBuilder {
public:
        void buildDough() {
                pizza_.dough("cross");
        }
 
        void buildSauce() {
                pizza_.sauce("mild");
        }
 
        void buildTopping() {
                pizza_.topping("ham+pineapple");
        }
};
 
class SpicyPizzaBuilder : public PizzaBuilder {
public:
        void buildDough() {
                pizza_.dough("pan baked");
        }
 
        void buildSauce() {
                pizza_.sauce("hot");
        }
 
        void buildTopping() {
                pizza_.topping("pepperoni+salami");
        }
};
 
class Cook {
public:
        Cook()
                : pizzaBuilder_(NULL/*nullptr*/)//Chinmay Mandal : nullptr replaced with NULL.
        {       }
 
        ~Cook() {
                if (pizzaBuilder_)
                        delete pizzaBuilder_;
        }
 
        void pizzaBuilder(PizzaBuilder* pizzaBuilder) {
                if (pizzaBuilder_)
                        delete pizzaBuilder_;
 
                pizzaBuilder_ = pizzaBuilder;
        }
 
        const Pizza& getPizza() {
                return pizzaBuilder_->pizza();
        }
 
        void constructPizza() {
                pizzaBuilder_->buildDough();
                pizzaBuilder_->buildSauce();
                pizzaBuilder_->buildTopping();
        }
 
private:
        PizzaBuilder* pizzaBuilder_;
};
 
int main() {
        Cook cook;
        cook.pizzaBuilder(new HawaiianPizzaBuilder);
        cook.constructPizza();
 
        Pizza hawaiian = cook.getPizza();
        hawaiian.open();
 
        cook.pizzaBuilder(new SpicyPizzaBuilder);
        cook.constructPizza();
 
        Pizza spicy = cook.getPizza();
        spicy.open();
}
在 PHP 中实现
<?php
/** "Product" */
class Pizza {

    protected $dough;
    protected $sauce;
    protected $topping;

    public function setDough($dough) {
        $this->dough = $dough;
    }

    public function setSauce($sauce) {
        $this->sauce = $sauce;
    }

    public function setTopping($topping) {
        $this->topping = $topping;
    }

    public function showIngredients() {
        echo "Dough   : ".$this->dough."<br/>";
        echo "Sauce   : ".$this->sauce."<br/>";
        echo "Topping : ".$this->topping."<br/>";
    }
}

/** "Abstract Builder" */
abstract class PizzaBuilder {

    protected $pizza;

    public function getPizza() {
        return $this->pizza;
    }

    public function createNewPizzaProduct() {
        $this->pizza = new Pizza();
    }

    public abstract function buildDough();
    public abstract function buildSauce();
    public abstract function buildTopping();
}

/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
    public function buildDough() {
        $this->pizza->setDough("cross");
    }

    public function buildSauce() {
        $this->pizza->setSauce("mild");
    }

    public function buildTopping() {
        $this->pizza->setTopping("ham + pineapple");
    }
}

/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {

    public function buildDough() {
        $this->pizza->setDough("pan baked");
    }

    public function buildSauce() {
        $this->pizza->setSauce("hot");
    }

    public function buildTopping() {
        $this->pizza->setTopping("pepperoni + salami");
    }
}

/** "Director" */
class Waiter {

    protected $pizzaBuilder;

    public function setPizzaBuilder(PizzaBuilder $pizzaBuilder) {
        $this->pizzaBuilder = $pizzaBuilder;
    }

    public function getPizza() {
        return $this->pizzaBuilder->getPizza();
    }

    public function constructPizza() {
        $this->pizzaBuilder->createNewPizzaProduct();
        $this->pizzaBuilder->buildDough();
        $this->pizzaBuilder->buildSauce();
        $this->pizzaBuilder->buildTopping();
    }
}

class Tester {

    public static function main() {

        $oWaiter               = new Waiter();
        $oHawaiianPizzaBuilder = new HawaiianPizzaBuilder();
        $oSpicyPizzaBuilder    = new SpicyPizzaBuilder();

        $oWaiter->setPizzaBuilder($oHawaiianPizzaBuilder);
        $oWaiter->constructPizza();

        $pizza = $oWaiter->getPizza();
        $pizza->showIngredients();

        echo "<br/>";

        $oWaiter->setPizzaBuilder($oSpicyPizzaBuilder);
        $oWaiter->constructPizza();

        $pizza = $oWaiter->getPizza();
        $pizza->showIngredients();
    }
}

Tester::main();

输出 

   Dough : cross
   Sauce : mild
   Topping : ham + pineapple
   Dough : pan baked
   Sauce : hot
   Topping : pepperoni + salami
在 Ruby 中实现
# Product
class Pizza
  attr_accessor :dough, :sauce, :topping
end

# Abstract Builder
class PizzaBuilder
  def get_pizza
    @pizza
  end

  def create_new_pizza_product
    @pizza = Pizza.new
  end

  def build_dough; end
  def build_sauce; end
  def build_topping; end

end

# ConcreteBuilder
class HawaiianPizzaBuilder < PizzaBuilder
  def build_dough
    @pizza.dough = 'cross'
  end
 
  def build_sauce
    @pizza.sauce = 'mild'
  end

  def build_topping
    @pizza.topping = 'ham+pineapple'
  end
end

# ConcreteBuilder
class SpicyPizzaBuilder < PizzaBuilder
  def build_dough
    @pizza.dough = 'pan baked'
  end

  def build_sauce
    @pizza.sauce = 'hot'
  end

  def build_topping
    @pizza.topping = 'pepperoni+salami'
  end
end

# Director
class Waiter
  attr_accessor :pizza_builder

  def get_pizza
    pizza_builder.get_pizza
  end

  def construct_pizza
    pizza_builder.create_new_pizza_product
    pizza_builder.build_dough
    pizza_builder.build_sauce
    pizza_builder.build_topping
  end
end
 
# A customer ordering a pizza.
class BuilderExample
  def main(args = [])
    waiter = Waiter.new
    hawaiian_pizza_builder = HawaiianPizzaBuilder.new
    spicy_pizza_builder = SpicyPizzaBuilder.new

    waiter.pizza_builder = hawaiian_pizza_builder
    waiter.construct_pizza

    pizza = waiter.get_pizza
  end
end

puts BuilderExample.new.main.inspect
在 Python 中实现
class Animal:
    """
    Abstract Animal
    """
    legs = 0
    tail = False
    roar = ''

class Mutator:
    """
    Mutator
    """
    def mutate(self):
        self.animal = Animal()

class Cat(Mutator):
    """
    Cat
    """
    def create_legs(self):
        self.animal.legs = 4
 
    def create_tail(self):
        self.animal.tail = True

    def create_roar(self):
        self.animal.roar = 'meowww!'

class Dog(Mutator):
    """
    Dog
    """
    def create_legs(self):
        self.animal.legs = 4

    def create_tail(self):
        self.animal.tail = True

    def create_roar(self):
        self.animal.roar = 'woffff!'

class AnimalOwner:
    """
    Farm owner
    """
    __mutator = ''
    def set_animal(self, mutator):
        self.__mutator = mutator

    def create_an_animal_for_me(self):
        self.__mutator.mutate()
        self.__mutator.create_legs()
        self.__mutator.create_tail()
        self.__mutator.create_roar()

    def get_animal(self):
        return self.__mutator.animal

c = Cat()
d = Dog()
ao = AnimalOwner()
ao.set_animal(c)
ao.create_an_animal_for_me()
animal = ao.get_animal()
print(animal.roar)  # meowww!
在 Delphi 中实现
program Builder;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
(*Product - final object that will be created by Director using Builder*)
  TPizza = class
    fDough: string;
    fSauce: string;
    fTopping: string;
    procedure Open;
  end;

  (*Builder - abstract class as interface for creating  objects -> product in this case*)
  TPizzaBuilder = class abstract
  protected
    fPizza: TPizza;
    public
    function GetPizza: TPizza;
    procedure CreateNewPizzaProduct;
    procedure BuildDough; virtual; abstract;
    procedure BuildSauce; virtual; abstract;
    procedure BuildTopping; virtual; abstract;
  end;

  (*concrete builder - provides implementation for Builder *)
  (*an object able to construct other objects.*)
  THawaiianPizzaBuilder = class(TPizzaBuilder)
    public
      procedure BuildDough; override;
      procedure BuildSauce; override;
      procedure BuildTopping; override;
  end;

  (*concrete builder = provides implenentation for Builder*)
  (*an object able to construct other objects.*)
  TSpicyPizzaBuilder = class(TPizzaBuilder)
    public
      procedure BuildDough; override;
      procedure BuildSauce; override;
      procedure BuildTopping; override;
  end;

  (*Director - responsible for managing the correct sequence of object creation.*)
  (*Receives a Concrete Builder as a parameter and executes the necessary operations on it.*)
  TCook = class
  protected
    fPizzaBuilder: TPizzaBuilder;
    public
      procedure SetPizzaBuilder(pb: TPizzaBuilder);
      function GetPizza: TPizza;
      procedure ConstructPizza;
  end;

{ THawaiianPizzaBuilder }

procedure THawaiianPizzaBuilder.BuildDough;
begin
  fPizza.fDough:= 'cross';
end;

procedure THawaiianPizzaBuilder.BuildSauce;
begin
  fPizza.fSauce:= 'mild';
end;

procedure THawaiianPizzaBuilder.BuildTopping;
begin
  fPizza.fTopping:= 'ham + pineapple';
end;

{ TSpicyPizzaBuilder }

procedure TSpicyPizzaBuilder.BuildDough;
begin
  fPizza.fDough:= 'pan baked';
end;

procedure TSpicyPizzaBuilder.BuildSauce;
begin
  fPizza.fSauce:= 'hot';
end;

procedure TSpicyPizzaBuilder.BuildTopping;
begin
  fPizza.fTopping:= 'pepperoni + salami';
end;

{ TCook }

procedure TCook.ConstructPizza;
begin
  fPizzaBuilder.CreateNewPizzaProduct;
  fPizzaBuilder.BuildDough;
  fPizzaBuilder.BuildSauce;
  fPizzaBuilder.BuildTopping;
end;

function TCook.GetPizza: TPizza;
begin
  Result:= fPizzaBuilder.GetPizza;
end;

procedure TCook.SetPizzaBuilder(pb: TPizzaBuilder);
begin
   fPizzaBuilder:= pb;
end;

{ TPizzaBuilder }

procedure TPizzaBuilder.CreateNewPizzaProduct;
begin
  fPizza:= TPizza.Create;
end;

function TPizzaBuilder.GetPizza: TPizza;
begin
   Result:= fPizza;
end;

{ TPizza }

procedure TPizza.Open;
begin
  WriteLn('Pizza with: ' + fDough + ' dough, ' +
  fSauce +' souce and '+fTopping +' topping. Mmm.');
end;

var
  cook: TCook;
  hawaiian, spicy: TPizza;

begin
  try
    { TODO -oUser -cConsole Main : Insert code here }

    cook:= TCook.Create;
    cook.SetPizzaBuilder(THawaiianPizzaBuilder.Create);
    cook.ConstructPizza;

    WriteLn('(* create the product *)');

    hawaiian:= cook.GetPizza;
    hawaiian.Open;

    WriteLn(#13#10+'(* create another product *)');

    cook.SetPizzaBuilder(TSpicyPizzaBuilder.Create);
    cook.ConstructPizza;

    spicy:= cook.GetPizza;
    spicy.Open;

    WriteLn(#13#10+'Press any key to continue...');
    ReadLn;

    spicy.Free;
    hawaiian.Free;
    cook.Free;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.


Clipboard

待办事项
添加更多使用示例。


桥接 计算机科学设计模式
建造者
责任链


你对本页有任何疑问吗?
在这里提问


在本手册中创建一个新页面


华夏公益教科书