建造者
建造者模式对于避免一个类中出现大量的构造函数非常有用。让我们想象一个存储交通方式的类(例如,一个员工的交通方式)。以下是一个以 MetroLine 对象作为参数的构造函数
modeOfTransport(MetroLine) |
现在我们需要一个构造函数,用于使用汽车、公交车或火车的人
new modeOfTransport(MetroLine)
new modeOfTransport(Train) |
对于其中一些,我们需要指定旅行津贴
new modeOfTransport(MetroLine)
new modeOfTransport(Train, Integer) |
我们有员工使用多种交通方式上班。然而,我们意识到构造函数列表现在已经变得很乱。每个新参数都会导致构造函数的指数级重复。如果某些参数具有相同的类型,它会变得非常混乱。解决这个问题的一个方法是先构建一个伪对象,然后通过调用其方法来填充它
new modeOfTransport(MetroLine)
modeOfTransport.setTravelAllowance(Integer) |
方法列表不再是指数级,但对象的状态可能不一致。更好的解决方案是将所有参数设置为另一个类的对象,一个预构造函数,然后将此对象传递给 ModeOfTransport 的构造函数
modeOfTransportPreConstructor.setMetroLine(MetroLine)
new modeOfTransport(ModeOfTransportPreConstructor) |
这个解决方案更好。我们只有一个有效的 ModeOfTransport 对象。但是,ModeOfTransport 构造函数可以使用半填充的预构造函数来调用。因此,预构造函数应该是一个建造者,应该有一个返回 ModeOfTransport 对象的方法。此方法仅在建造者被正确填充后才会返回对象,否则返回 null
modeOfTransportBuilder.setMetroLine(MetroLine)
modeOfTransport := modeOfTransportBuilder.getResult() |
因此,解决方案是使用建造者类。让我们在 UML 类图中查看代码的结构
- 建造者:用于创建对象(产品)的抽象接口。
- 具体建造者:为建造者提供实现。它是一个能够构建其他对象的物体。构建并组装部件来构建物体。
建造者模式可用于包含扁平数据(html 代码、SQL 查询、X.509 证书等)的对象,即无法轻松编辑的数据。这种类型的数据无法一步步编辑,必须一次性编辑。构建此类对象的最佳方式是使用建造者类。
示例
在 Java 中,StringBuffer
和 StringBuilder
类遵循建造者设计模式。它们用于构建 String
对象。
成本
你可以很容易地决定是否使用它。最糟糕的情况是,模式是无用的。
创建
从一个具有公共构造函数的普通类开始,实现设计模式并不昂贵。你可以在代码旁边创建建造者类。然后,你将不得不删除现有的构造函数调用,以便改用建造者。重构几乎不是自动的。
维护
此设计模式只有很小的缺点。它可能会导致类和建造者结构之间出现小的冗余,但两个类通常具有不同的结构。但是,转换为抽象工厂很昂贵。
移除
重构几乎不是自动的。它应该手动完成。
建议
- 在建造者类的名称中添加建造者一词,以便向其他开发人员表明使用了该模式。
- 将你的建造者类构建为一个流畅的接口。这将增加模式的趣味性。
- 如果目标类包含扁平数据,你的建造者类可以构建为一个组合,它实现了解释器模式。
实现
制造汽车。
/**
* 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();
}
}
在上面的例子中,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++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
/** "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
# 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
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!
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.