Строитель (шаблон проектирования)
Строитель (англ. Builder) — порождающий шаблон проектирования предоставляет способ создания составного объекта.
Строитель | |
---|---|
Builder | |
Тип | Порождающий |
Плюсы |
Позволяет изменять внутреннее представление продукта. Изолирует код, реализующий конструирование и представление. Дает более тонкий контроль над процессом конструирования, чем другие порождающие паттерны |
Родственные шаблоны | Абстрактная фабрика, Компоновщик |
Описан в Design Patterns | Да |
Цель
Отделяет конструирование сложного объекта от его представления так, что в результате одного и того же процесса конструирования могут получаться разные представления.
Плюсы
- позволяет изменять внутреннее представление продукта;
- изолирует код, реализующий конструирование и представление;
- дает более тонкий контроль над процессом конструирования.
Минусы
- алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой;
- процесс конструирования должен обеспечивать различные представления конструируемого объекта.
Применение
Объекты «моникер» в COM есть Строители, инициализируемые строкой. Более того, для их создания используется другой Строитель — MkParseDisplayNameEx, который определяет по строке класс моникера, создает моникер и инициализирует его этой же строкой.
Один из этих объектов, URL Moniker, используется для всей загрузки страниц, вложений и документов в Microsoft Internet Explorer.
Примеры
Java
/** "Product" */
class Pizza {
private String dough = "";
private String sauce = "";
private String topping = "";
public void setDough(String dough) { this.dough = dough; }
public void setSauce(String sauce) { this.sauce = sauce; }
public void setTopping(String topping) { this.topping = topping; }
}
/** "Abstract Builder" */
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();
}
/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
public void buildDough() { pizza.setDough("cross"); }
public void buildSauce() { pizza.setSauce("mild"); }
public void buildTopping() { pizza.setTopping("ham+pineapple"); }
}
/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
public void buildDough() { pizza.setDough("pan baked"); }
public void buildSauce() { pizza.setSauce("hot"); }
public void buildTopping() { pizza.setTopping("pepperoni+salami"); }
}
/** "Director" */
class Waiter {
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();
}
}
/** A customer ordering a pizza. */
public class BuilderExample {
public static void main(String[] args) {
Waiter waiter = new Waiter();
PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
waiter.setPizzaBuilder(hawaiianPizzaBuilder);
waiter.constructPizza();
Pizza pizza = waiter.getPizza();
}
}
// паттерн Builder
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Обязательные параметры
private final int servingSize;
private final int servings;
// Дополнительные параметры - инициализируются значениями по умолчанию
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
// usage
NutritionFacts cocaCola = new NutritionFacts
.Builder(240, 8)
.calories(100)
.sodium(35)
.carbohydrate(27)
.build();
Scala
package com
package object builder {
class Pizza {
private var dough: String = ""
private var sauce: String = ""
private var topping: String = ""
def setDough(dough: String) : Unit = {
this.dough = dough
}
def setSauce(sauce: String) : Unit = {
this.sauce = sauce
}
def setTopping(topping: String) : Unit = {
this.topping = topping
}
def outputReceipt() : Unit = {
println(s"Dough: $dough\nSauce: $sauce\nTopping: $topping")
}
}
abstract class AbstractPizzaBuilder {
protected var pizza : Option[Pizza] = None
def getPizza : Option[Pizza] = pizza
def createPizza() : Unit = {
pizza = Some(new Pizza)
}
def buildDough() : Unit
def buildSauce() : Unit
def buildTopping() : Unit
}
class HawaiianPizzaBuilder extends AbstractPizzaBuilder {
override def buildDough() : Unit = {
pizza.get.setDough("cross")
}
override def buildSauce() : Unit = {
pizza.get.setSauce("mild")
}
override def buildTopping() : Unit = {
pizza.get.setTopping("ham+pineapple")
}
}
class SpicyPizzaBuilder extends AbstractPizzaBuilder {
override def buildDough() : Unit = {
pizza.get.setDough("pan baked")
}
override def buildSauce() : Unit = {
pizza.get.setSauce("hot")
}
override def buildTopping() : Unit = {
pizza.get.setTopping("pepperoni+salami")
}
}
class Waiter {
private var pizzaBuilder : Option[AbstractPizzaBuilder] = None
def setPizzaBuilder(pizzaBuilder: AbstractPizzaBuilder) : Unit = {
this.pizzaBuilder = Some(pizzaBuilder)
println(s"Builder ${pizzaBuilder.getClass.getName} is set as default")
}
def createPizza() : Pizza = {
pizzaBuilder.get.createPizza()
pizzaBuilder.get.buildDough()
pizzaBuilder.get.buildSauce()
pizzaBuilder.get.buildTopping()
pizzaBuilder.get.getPizza.get
}
}
object BuilderTest {
def main(args: Array[String]) : Unit = {
val waiter = new Waiter
println("Output:")
waiter.setPizzaBuilder(new HawaiianPizzaBuilder)
waiter.createPizza().outputReceipt()
waiter.setPizzaBuilder(new SpicyPizzaBuilder)
waiter.createPizza().outputReceipt()
}
}
}
// Output:
// Builder com.builder.package$HawaiianPizzaBuilder is set as default
// Dough: cross
// Sauce: mild
// Topping: ham+pineapple
// Builder com.builder.package$SpicyPizzaBuilder is set as default
// Dough: pan baked
// Sauce: hot
// Topping: pepperoni+salami
С#
using System;
using System.Collections.Generic;
namespace Builder
{
public class MainApp
{
public static void Main()
{
// Create director and builders
Director director = new Director();
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
// Construct two products
director.Construct(b1);
Product p1 = b1.GetResult();
p1.Show();
director.Construct(b2);
Product p2 = b2.GetResult();
p2.Show();
// Wait for user
Console.Read();
}
}
// "Director"
class Director
{
// Builder uses a complex series of steps
public void Construct(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
}
// "Builder"
abstract class Builder
{
public virtual void BuildPartA(){}
public virtual void BuildPartB(){}
public abstract Product GetResult();
}
// "ConcreteBuilder1"
class ConcreteBuilder1 : Builder
{
private readonly Product product = new Product();
public override void BuildPartA()
{
product.Add("PartA");
}
public override void BuildPartB()
{
product.Add("PartB");
}
public override Product GetResult()
{
return product;
}
}
// "ConcreteBuilder2"
class ConcreteBuilder2 : Builder
{
private readonly Product product = new Product();
public override void BuildPartA()
{
product.Add("PartX");
}
public override void BuildPartB()
{
product.Add("PartY");
}
public override Product GetResult()
{
return product;
}
}
// "Product"
class Product
{
private readonly List<string> parts = new List<string>();
public void Add(string part)
{
parts.Add(part);
}
public void Show()
{
Console.WriteLine("\nProduct Parts -------");
foreach (string part in parts)
Console.WriteLine(part);
}
}
}
C++
// Реализация на C++.
#include <iostream>
#include <memory>
#include <string>
// Product
class Pizza
{
private:
std::string dough;
std::string sauce;
std::string topping;
public:
Pizza() { }
~Pizza() { }
void SetDough(const std::string& d) { dough = d; }
void SetSauce(const std::string& s) { sauce = s; }
void SetTopping(const std::string& t) { topping = t; }
void ShowPizza()
{
std::cout << " Yummy !!!" << std::endl
<< "Pizza with Dough as " << dough
<< ", Sauce as " << sauce
<< " and Topping as " << topping
<< " !!! " << std::endl;
}
};
// Abstract Builder
class PizzaBuilder
{
protected:
std::shared_ptr<Pizza> pizza;
public:
PizzaBuilder() {}
virtual ~PizzaBuilder() {}
std::shared_ptr<Pizza> GetPizza() { return pizza; }
void createNewPizzaProduct() { pizza.reset (new Pizza); }
virtual void buildDough()=0;
virtual void buildSauce()=0;
virtual void buildTopping()=0;
};
// ConcreteBuilder
class HawaiianPizzaBuilder : public PizzaBuilder
{
public:
HawaiianPizzaBuilder() : PizzaBuilder() {}
~HawaiianPizzaBuilder(){}
void buildDough() { pizza->SetDough("cross"); }
void buildSauce() { pizza->SetSauce("mild"); }
void buildTopping() { pizza->SetTopping("ham and pineapple"); }
};
// ConcreteBuilder
class SpicyPizzaBuilder : public PizzaBuilder
{
public:
SpicyPizzaBuilder() : PizzaBuilder() {}
~SpicyPizzaBuilder() {}
void buildDough() { pizza->SetDough("pan baked"); }
void buildSauce() { pizza->SetSauce("hot"); }
void buildTopping() { pizza->SetTopping("pepperoni and salami"); }
};
// Director
class Waiter
{
private:
PizzaBuilder* pizzaBuilder;
public:
Waiter() : pizzaBuilder(nullptr) {}
~Waiter() { }
void SetPizzaBuilder(PizzaBuilder* b) { pizzaBuilder = b; }
std::shared_ptr<Pizza> GetPizza() { return pizzaBuilder->GetPizza(); }
void ConstructPizza()
{
pizzaBuilder->createNewPizzaProduct();
pizzaBuilder->buildDough();
pizzaBuilder->buildSauce();
pizzaBuilder->buildTopping();
}
};
// Клиент заказывает две пиццы.
int main()
{
Waiter waiter;
HawaiianPizzaBuilder hawaiianPizzaBuilder;
waiter.SetPizzaBuilder (&hawaiianPizzaBuilder);
waiter.ConstructPizza();
std::shared_ptr<Pizza> pizza = waiter.GetPizza();
pizza->ShowPizza();
SpicyPizzaBuilder spicyPizzaBuilder;
waiter.SetPizzaBuilder(&spicyPizzaBuilder);
waiter.ConstructPizza();
pizza = waiter.GetPizza();
pizza->ShowPizza();
return EXIT_SUCCESS;
}
JavaScript
// Product
function Pizza() {
var dublicate = this; // постоянная ссылка на инстанцируемый объект для вызова при любом this
var dough;
var sauce;
var topping;
this.setDough = function(val) {
dough = val;
};
this.setSauce = function(val) {
sauce = val;
};
this.setTopping = function(val) {
topping = val;
};
// из-за особенностей языка, геттеры (пусть они нам и не понадобятся)
// должны быть определены в той же функции, что и локальные переменные
this.getDough = function() {
return dough;
};
this.getSauce = function() {
return sauce;
};
this.getTopping = function() {
return topping;
};
// мы должны создать метод, изменяющий св-ва уже созданного объекта
// (см. createNewPizzaProduct)
this.clear = function() {
dublicate.setDough(undefined);
dublicate.setSauce(undefined);
dublicate.setTopping(undefined);
};
}
// Abstract Builder
function PizzaBuilder() {
var pizza = new Pizza();
this.getPizza = function() {
return pizza;
};
this.createNewPizzaProduct = function() {
// если мы просто поменяем зн-е переменной pizza, то изменение никак
// не отразится на дочерних классах, т.к. внутри них переменная pizza
// ссылается на «старую» область памяти
pizza.clear();
// если внутри реализаций (HawaiianPizzaBuilder, SpicyPizzaBuilder)
// мы, вместо переменной pizza, будем использовать метод getPizza,
// то можно использовать
// pizza = new Pizza();
// и метод clear у Pizza не понадобится
};
this.buildDough = function(val) { };
this.buildSauce = function(val) { };
this.buildTopping = function(val) { };
}
// ConcreteBuilder
function HawaiianPizzaBuilder() {
PizzaBuilder.call(this);
var pizza = this.getPizza(); // имитация protected
this.buildDough = function() { pizza.setDough("cross"); };
this.buildSauce = function() { pizza.setSauce("mild"); };
this.buildTopping = function() { pizza.setTopping("ham+pineapple"); };
}
function SpicyPizzaBuilder() {
PizzaBuilder.call(this);
var pizza = this.getPizza();
this.buildDough = function() { pizza.setDough("pan baked"); };
this.buildSauce = function() { pizza.setSauce("hot"); };
this.buildTopping = function() { pizza.setTopping("pepperoni+salami"); };
}
// Director
function Waiter() {
var pizzaBuilder;
this.setPizzaBuilder = function(builder) {
pizzaBuilder = builder;
};
this.getPizza = function() {
return pizzaBuilder.getPizza();
};
this.constructPizza = function() {
pizzaBuilder.createNewPizzaProduct();
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildTopping();
};
}
// Клиент заказывает две пиццы
var pizza;
var waiter = new Waiter();
var hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
waiter.setPizzaBuilder( hawaiianPizzaBuilder );
waiter.constructPizza();
pizza = waiter.getPizza();
alert( pizza.getDough() +", "+ pizza.getSauce() +", "+ pizza.getTopping() );
var spicyPizzaBuilder = new SpicyPizzaBuilder();
waiter.setPizzaBuilder( spicyPizzaBuilder );
waiter.constructPizza();
pizza = waiter.getPizza();
alert( pizza.getDough() +", "+ pizza.getSauce() +", "+ pizza.getTopping() );
Python
#coding: utf-8
class Animal:
"""
Абстрактное Животное
"""
legs = 0
tail = False
roar = ''
class Mutator:
"""
Ответственный за размножение
"""
def mutate(self):
self.animal = Animal()
class Cat(Mutator):
"""
Кошка
"""
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):
"""
Собака
"""
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:
"""
Владелец питомника
"""
__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!
PHP5
<?php
/**
* Паттерн строитель, оперирует известными "рецептами строительства"
*/
/**
* Pizza - Базовый объект строительства
*/
class Pizza {
private $_pastry = "";
private $_sauce = "";
private $_garniture = "";
public function setPastry($pastry) {
$this->_pastry = $pastry;
}
public function setSauce($sauce) {
$this->_sauce = $sauce;
}
public function setGarniture($garniture) {
$this->_garniture = $garniture;
}
}
/**
* Builder - Абстрактный строитель
*/
abstract class BuilderPizza {
protected $_pizza;
public function getPizza() {
return $this->_pizza;
}
public function createNewPizza() {
$this->_pizza = new Pizza ();
}
abstract public function buildPastry();
abstract public function buildSauce();
abstract public function buildGarniture();
}
/**
* BuilderConcret - Конкретный строитель 1
*/
class BuilderPizzaHawaii extends BuilderPizza {
public function buildPastry() {
$this->_pizza->setPastry ( "normal" );
}
public function buildSauce() {
$this->_pizza->setSauce ( "soft" );
}
public function buildGarniture() {
$this->_pizza->setGarniture ( "jambon+ananas" );
}
}
/**
* BuilderConcret - Конкретный строитель 2
*/
class BuilderPizzaSpicy extends BuilderPizza {
public function buildPastry() {
$this->_pizza->setPastry ( "puff" );
}
public function buildSauce() {
$this->_pizza->setSauce ( "hot" );
}
public function buildGarniture() {
$this->_pizza->setGarniture ( "pepperoni+salami" );
}
}
/**
* Director - Управляющий класс, запускающий строительство
* PizzaBuilder - Реализация патерна Builder, показывающая делегирование процесса создания пиццы методу constructPizza
*/
class PizzaBuilder {
private $_builderPizza;
public function setBuilderPizza(BuilderPizza $mp)
{
$this->_builderPizza = $mp;
}
public function getPizza()
{
return $this->_builderPizza->getPizza();
}
public function constructPizza() {
$this->_builderPizza->createNewPizza ();
$this->_builderPizza->buildPastry ();
$this->_builderPizza->buildSauce ();
$this->_builderPizza->buildGarniture ();
}
}
// Инициализация разносчика
$pizzaBuilder = new PizzaBuilder();
// Инициализация доступных продуктов
$builderPizzaHawaii = new BuilderPizzaHawaii();
$builderPizzaPiquante = new BuilderPizzaSpicy();
// Подготовка и получение продукта
$pizzaBuilder->setBuilderPizza( $builderPizzaHawaii );
$pizzaBuilder->constructPizza();
$pizza = $pizzaBuilder->getPizza();
Ruby
#
# Базовый объект строительства
#
class Pizza
attr_accessor :pastry, :sauce, :garniture
end
#
# Builder - класс строитель
#
class BuilderPizza
attr_reader :pizza
def create_new_pizza
@pizza = Pizza.new
end
def get_pizza
"Your order. pastry: #{@pizza.pastry}, sauce: #{@pizza.sauce}, garniture: #{@pizza.garniture}"
end
end
#
# BuilderConcret - Конкретный строитель 1
#
class BuilderPizzaHawaii < BuilderPizza
def build_pastry
@pizza.pastry = 'normal'
end
def build_sauce
@pizza.sauce = 'soft'
end
def build_garniture
@pizza.garniture = 'jambon+ananas'
end
end
#
# BuilderConcret - Конкретный строитель 2
#
class BuilderPizzaSpicy < BuilderPizza
def build_pastry
@pizza.pastry = 'puff'
end
def build_sauce
@pizza.sauce = 'hot'
end
def build_garniture
@pizza.garniture = 'papperoni+salami'
end
end
#
# Director - Управляющий класс, запускающий строительство
#
class Waiter
def set_builder_pizza(bp)
@builder_pizza = bp
end
def get_pizza
@builder_pizza.get_pizza
end
def construct_pizza
@builder_pizza.create_new_pizza
@builder_pizza.build_pastry
@builder_pizza.build_sauce
@builder_pizza.build_garniture
end
end
waiter = Waiter.new
builder_pizza_hawaii = BuilderPizzaHawaii.new
builder_pizza_spicy = BuilderPizzaSpicy.new
waiter.set_builder_pizza(builder_pizza_hawaii)
waiter.construct_pizza
puts waiter.get_pizza
Delphi
program BuilderPatternExample;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
// Product
TPizza = class(TObject)
strict private
FDough, FSauce, FTopping: string;
public
property Dough: string write FDough;
property Sauce: string write FSauce;
property Topping: string write FTopping;
procedure Show;
end;
// Abstract Builder
TPizzaBuilder = class(TObject)
strict protected
FPizza: TPizza;
public
property Pizza: TPizza read FPizza;
constructor Create;
destructor Destroy; override;
procedure CreateNewPizzaProduct;
procedure FreePizzaProduct;
procedure BuildDough; virtual; abstract;
procedure BuildSauce; virtual; abstract;
procedure BuildTopping; virtual; abstract;
end;
// Concrete Builder A
THawaiianPizzaBuilder = class(TPizzaBuilder)
public
procedure BuildDough; override;
procedure BuildSauce; override;
procedure BuildTopping; override;
end;
// Concrete Builder B
TSpicyPizzaBuilder = class(TPizzaBuilder)
public
procedure BuildDough; override;
procedure BuildSauce; override;
procedure BuildTopping; override;
end;
// Director
TWaiter = class(TObject)
strict private
FPizzaBuilder: TPizzaBuilder;
public
property PizzaBuilder: TPizzaBuilder write FPizzaBuilder;
constructor Create;
destructor Destroy; override;
procedure ConstructPizza;
procedure FreePizza;
function GetPizza: TPizza;
end;
{ TPizza }
procedure TPizza.Show;
begin
WriteLn('Pizza with Dough as ' + FDough + ', sauce as ' + FSauce + ' and Topping as ' + FTopping + '!');
end;
{ TPizzaBuilder }
constructor TPizzaBuilder.Create;
begin
FPizza := nil;
end;
destructor TPizzaBuilder.Destroy;
begin
FreePizzaProduct;
inherited Destroy;
end;
procedure TPizzaBuilder.FreePizzaProduct;
begin
if FPizza <> nil then
FreeAndNil(FPizza);
end;
procedure TPizzaBuilder.CreateNewPizzaProduct;
begin
if FPizza <> nil then
FPizza.Free;
FPizza := TPizza.Create;
end;
{ THawaiianPizzaBuilder }
procedure THawaiianPizzaBuilder.BuildDough;
begin
if FPizza <> nil then
FPizza.Dough := 'cross';
end;
procedure THawaiianPizzaBuilder.BuildSauce;
begin
if FPizza <> nil then
FPizza.Sauce := 'mild';
end;
procedure THawaiianPizzaBuilder.BuildTopping;
begin
if FPizza <> nil then
FPizza.Topping := 'ham and pineapple';
end;
{ TSpicyPizzaBuilder }
procedure TSpicyPizzaBuilder.BuildDough;
begin
if FPizza <> nil then
FPizza.Dough := 'pan baked';
end;
procedure TSpicyPizzaBuilder.BuildSauce;
begin
if FPizza <> nil then
FPizza.Sauce := 'hot';
end;
procedure TSpicyPizzaBuilder.BuildTopping;
begin
if FPizza <> nil then
FPizza.Topping := 'pepperoni and salami';
end;
{ TWaiter }
constructor TWaiter.Create;
begin
FPizzaBuilder := nil;
end;
destructor TWaiter.Destroy;
begin
FPizzaBuilder := nil;
inherited Destroy;
end;
procedure TWaiter.FreePizza;
begin
if FPizzaBuilder <> nil then
FPizzaBuilder.FreePizzaProduct;
end;
procedure TWaiter.ConstructPizza;
begin
if FPizzaBuilder <> nil then
begin
FPizzaBuilder.CreateNewPizzaProduct;
FPizzaBuilder.BuildDough;
FPizzaBuilder.BuildSauce;
FPizzaBuilder.BuildTopping;
end;
end;
function TWaiter.GetPizza: TPizza;
begin
if FPizzaBuilder <> nil then
Result := FPizzaBuilder.Pizza
else
Result := nil;
end;
procedure ConstructAndShowPizza(Waiter: TWaiter; Builder: TPizzaBuilder);
var
Pizza: TPizza;
begin
Waiter.PizzaBuilder := Builder;
Waiter.ConstructPizza;
Pizza := Waiter.GetPizza;
try
Pizza.Show;
finally
Waiter.FreePizza;
end;
end;
var
Waiter: TWaiter;
HawaiianPizzaBuilder: THawaiianPizzaBuilder;
SpicyPizzaBuilder: TSpicyPizzaBuilder;
begin
HawaiianPizzaBuilder := nil;
SpicyPizzaBuilder := nil;
Waiter := nil;
try
HawaiianPizzaBuilder := THawaiianPizzaBuilder.Create;
SpicyPizzaBuilder := TSpicyPizzaBuilder.Create;
Waiter := TWaiter.Create;
// Client has ordered two pizzas
ConstructAndShowPizza(Waiter, HawaiianPizzaBuilder);
ConstructAndShowPizza(Waiter, SpicyPizzaBuilder);
finally
Waiter.Free;
HawaiianPizzaBuilder.Free;
SpicyPizzaBuilder.Free;
end;
ReadLn;
end.
VB.NET
Imports System.Collections.Generic
Namespace Builder
Public Class MainApp
Public Shared Sub Main()
' Create director and builders
Dim director As New Director()
Dim b1 As Builder = New ConcreteBuilder1()
Dim b2 As Builder = New ConcreteBuilder2()
' Construct two products
director.Construct(b1)
Dim p1 As Product = b1.GetResult()
p1.Show()
director.Construct(b2)
Dim p2 As Product = b2.GetResult()
p2.Show()
' Wait for user
Console.Read()
End Sub
End Class
' "Director"
Class Director
' Builder uses a complex series of steps
Public Sub Construct(ByVal builder As Builder)
builder.BuildPartA()
builder.BuildPartB()
End Sub
End Class
' "Builder"
MustInherit Class Builder
Public MustOverride Sub BuildPartA()
Public MustOverride Sub BuildPartB()
Public MustOverride Function GetResult() As Product
End Class
' "ConcreteBuilder1"
Class ConcreteBuilder1
Inherits Builder
Private ReadOnly product As New Product()
Public Overrides Sub BuildPartA()
product.Add("PartA")
End Sub
Public Overrides Sub BuildPartB()
product.Add("PartB")
End Sub
Public Overrides Function GetResult() As Product
Return product
End Function
End Class
' "ConcreteBuilder2"
Class ConcreteBuilder2
Inherits Builder
Private ReadOnly product As New Product()
Public Overrides Sub BuildPartA()
product.Add("PartX")
End Sub
Public Overrides Sub BuildPartB()
product.Add("PartY")
End Sub
Public Overrides Function GetResult() As Product
Return product
End Function
End Class
' "Product"
Class Product
Private ReadOnly parts As New List(Of String)()
Public Sub Add(ByVal part As String)
parts.Add(part)
End Sub
Public Sub Show()
Console.WriteLine(vbLf & "Product Parts -------")
For Each part As String In parts
Console.WriteLine(part)
Next
End Sub
End Class
End Namespace