Строитель (шаблон проектирования)

Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Перейти к навигацииПерейти к поиску

Строитель, (англ. Builder)порождающий шаблон проектирования.

Цель

Отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления.

Плюсы

  • позволяет изменять внутреннее представление продукта;
  • изолирует код, реализующий конструирование и представление;
  • дает более тонкий контроль над процессом конструирования.

Применение

  • алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой;
  • процесс конструирования должен обеспечивать различные представления конструируемого объекта.
Файл:Builder.gif

Примеры

Пример на Java

<source lang="java">

/** "Product" Maksatzadr*/
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. */
class BuilderExample {
   public static void main(String[] args) {
       Waiter waiter = new Waiter();
       PizzaBuilder hawaiian_pizzabuilder = new HawaiianPizzaBuilder();
       PizzaBuilder spicy_pizzabuilder = new SpicyPizzaBuilder();
       waiter.setPizzaBuilder( hawaiian_pizzabuilder );
       waiter.constructPizza();
       Pizza pizza = waiter.getPizza();
   }
}

</source>

Пример на С#

<source lang="csharp">

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 abstract void BuildPartA();
   public abstract 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);
   }
 }
}

</source>

Пример на C++

<source lang="cpp"> // Реализация на C++.

  1. include <iostream>
  2. include <memory>
  3. 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::auto_ptr<Pizza> pizza;

public:

   PizzaBuilder() {}
   virtual ~PizzaBuilder() {}
   std::auto_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(NULL) {}
   ~Waiter() { }
   
   void SetPizzaBuilder(PizzaBuilder* b) { pizzaBuilder = b; }
   std::auto_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::auto_ptr<Pizza> pizza = waiter.GetPizza();
   pizza->ShowPizza();
   
   SpicyPizzaBuilder spicyPizzaBuilder;
   waiter.SetPizzaBuilder(&spicyPizzaBuilder);
   waiter.ConstructPizza();
   pizza = waiter.GetPizza();
   pizza->ShowPizza();
 
   return EXIT_SUCCESS;

} </source>

Пример на JavaScript

<source lang="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() ); </source>

Вариант (урезанный) без использования локальной переменной dublicate и метода clear у Pizza

<source lang="javascript"> // Product function Pizza() { var dough; var sauce; var topping;

// методы setDough, setSauce, setTopping, getDough, getSauce, getTopping без изменений // метод clear не нужен }

// Abstract Builder function PizzaBuilder() { var pizza = new Pizza();

this.getPizza = function() { return pizza; }; this.createNewPizzaProduct = function() { // внутри реализаций (HawaiianPizzaBuilder, SpicyPizzaBuilder) // будем использовать метод getPizza pizza = new Pizza(); };

this.buildDough = function(val) { }; this.buildSauce = function(val) { }; this.buildTopping = function(val) { }; }

// ConcreteBuilder function HawaiianPizzaBuilder() { PizzaBuilder.call(this); // вместо имитации protected будем использовать ссылку на геттер var pizza = this.getPizza;

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 pizza; var waiter = new Waiter();

var hawaiianPizzaBuilder = new HawaiianPizzaBuilder(); waiter.setPizzaBuilder( hawaiianPizzaBuilder ); waiter.constructPizza(); pizza = waiter.getPizza(); // возвращенный объект теперь не изменится при constructPizza waiter.constructPizza(); pizza2 = waiter.getPizza(); alert( pizza.getDough() +", "+ pizza.getSauce() +", "+ pizza.getTopping() ); alert( pizza2.getDough() +", "+ pizza2.getSauce() +", "+ pizza2.getTopping() );

var spicyPizzaBuilder = new SpicyPizzaBuilder(); waiter.setPizzaBuilder( spicyPizzaBuilder ); waiter.constructPizza(); pizza = waiter.getPizza(); alert( pizza.getDough() +", "+ pizza.getSauce() +", "+ pizza.getTopping() ); </source>



порождающие шаблоны проектирования
абстрактная фабрика | строитель | фабричный метод | прототип | одиночка | отложенная инициализация

bg:Строител (шаблон) ca:Builder de:Erbauer (Entwurfsmuster) en:Builder pattern es:Builder (patrón de diseño) fr:Monteur (patron de conception) it:Builder ja:Builder パターン ko:빌더 패턴 pl:Budowniczy (wzorzec projektowy) pt:Builder uk:Будівник (шаблон проектування) zh:生成器 (设计模式)

Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....