建造者
建造者模式對於避免一個類中出現大量的建構函式非常有用。讓我們想象一個儲存交通方式的類(例如,一個員工的交通方式)。以下是一個以 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.
