Будівельник (шаблон проєктування) — Вікіпедія
Будівельник (англ. Builder) — шаблон проєктування, належить до класу твірних шаблонів. На відміну від шаблону абстрактної фабрики і фабричного методу, ціль яких є застосування поліморфізму, задачею шаблону будівельника є забезпечення реалізації антишаблону телескопічного (багатоступеневого) конструювання. Антишаблон «телескопічний конструктор» коли різна комбінація параметрів конструктора призводить до появи експоненційної множини конструкторів. Замість того, щоб використовувати набір конструкторів, використовують шаблон будівельник, згідно з яким використовують інший об'єкт (будівельник), що отримує на вхід вхідні параметри по одному, крок за кроком, і повертає за один прохід результуючий створений об'єкт.
Призначення[ред. | ред. код]
Відокремлює конструювання складного об'єкта від його подання, таким чином у результаті одного й того ж процесу конструювання можуть бути отримані різні подання.
Мотивація[ред. | ред. код]
Вам запропоновано створити систему планування екскурсій по Паттернленду — новому парку розваг. Гості парку можуть вибрати готель, замовити квитки на атракціони, зарезервувати місця в ресторані і навіть замовити спеціальні заходи. Поїздки можуть відрізнятися за кількістю днів і складу розважальної програми. Наприклад, місцевий житель не бажає зупинятися у готелі, але хоче замовити обід та спеціальні заходи. Другий гість прилітає літаком і йому необхідно забронювати номер в готелі, столик в ресторані і квитки на заходи. Таким чином, нам потрібна гнучка структура даних, яка може представляти програму поселення з усіма можливими варіаціями; крім того, побудова програми може складатися з декількох кроків.
Застосування[ред. | ред. код]
Слід використовувати шаблон Будівельник коли:
- алгоритм створення складного об'єкта не повинен залежати від того, з яких частин складається об'єкт та як вони стикуються поміж собою;
- процес конструювання повинен забезпечити різні подання об'єкта, що конструюється.
Структура[ред. | ред. код]
- Builder — будівельник:
- визначає абстрактний інтерфейс для створення частин об'єкта Product;
- ConcreteBuilder — конкретний будівельник:
- конструює та збирає докупи частини продукту шляхом реалізації інтерфейсу Builder;
- визначає подання, що створюється, та слідкує на ним;
- надає інтерфейс для доступу до продукту;
- Director — керівник:
- конструює об'єкт, користуючись інтерфейсом Builder;
- Product — продукт:
- подає складний конструйований об'єкт. ConcreteBuilder будує внутрішнє подання продукту та визначає процес його складання;
- вносить класи, що визначають складені частини, у тому числі інтерфейси для складання кінцевого результату з частин.
Переваги[ред. | ред. код]
- дозволяє змінювати внутрішнє представлення продукту;
- ізолює код, який реалізує конструювання та подання;
- дає тонший контроль над процесом конструювання.
Недоліки[ред. | ред. код]
- Потрібно створити окремий ConcreteBuilder для кожного окремого продукту.
Відносини[ред. | ред. код]
- клієнт створює об'єкт-управитель Director та конфігурує його потрібним об'єктом-будівником Builder;
- управитель повідомляє будівельника про те, що потрібно побудувати наступну частину продукту;
- будівельник оброблює запити управителя та додає нові частини до продукту;
- клієнт забирає продукт у будівельника.
Реалізація[ред. | ред. код]
Приклад С++[ред. | ред. код]
#include <iostream> #include <string> using namespace std; // Builder class CReportBuilder { public: virtual ~CReportBuilder() {}; virtual void CreateHeader() = 0; virtual void CreateBody() = 0; virtual void CreateFooter() = 0; virtual void Print() { cout << m_strReport << endl; }; protected: string m_strReport; }; // Конкретний будівельник 1 struct CTextReportBuilder : public CReportBuilder { virtual ~CTextReportBuilder() {}; virtual void CreateHeader() { m_strReport.append("SIMPLE REPORT'S HEADER \n"); }; virtual void CreateBody() { m_strReport.append("\n\"Simple Report's Main Text\"\n \n"); }; virtual void CreateFooter() { m_strReport.append("Simple Report's Footer \n"); }; }; // Конкретний будівельник 2 struct CHTMLReportBuilder : public CReportBuilder { virtual ~CHTMLReportBuilder() {}; virtual void CreateHeader() { m_strReport.append("<HTML><BODY> \n"); m_strReport.append("<H1>HTML REPORT'S HEADER</H1> \n"); }; virtual void CreateBody() { m_strReport.append("<p>\"HTML Report's Main Text\"</p> \n"); }; virtual void CreateFooter() { m_strReport.append("<p><i>HTML Report's Footer</i></p> \n"); m_strReport.append("</BODY></HTML>"); }; }; // Director. Створює продукт використовуючи інтерфейс Будівельника void CreateReport(CReportBuilder& report) { report.CreateHeader(); report.CreateBody(); report.CreateFooter(); }; void main() { CHTMLReportBuilder Report; // Product CreateReport(Report); Report.Print(); }
Приклад Swift[ред. | ред. код]
class DeathStarBuilder { var x: Double? var y: Double? var z: Double? typealias BuilderClosure = (DeathStarBuilder) -> () init(buildClosure: BuilderClosure) { buildClosure(self) } } struct DeathStar : CustomStringConvertible { let x: Double let y: Double let z: Double init?(builder: DeathStarBuilder) { if let x = builder.x, y = builder.y, z = builder.z { self.x = x self.y = y self.z = z } else { return nil } } var description:String { return "Death Star at (x:\(x) y:\(y) z:\(z))" } } let empire = DeathStarBuilder { builder in builder.x = 0.1 builder.y = 0.2 builder.z = 0.3 } let deathStar = DeathStar(builder:empire)
Джерела[ред. | ред. код]
- Design Patterns: Elements of Reusable Object-Oriented Software [Архівовано 9 листопада 2012 у Wayback Machine.]
- Design Patterns implemented in Swift 2 [Архівовано 30 січня 2016 у Wayback Machine.]
Література[ред. | ред. код]
Алан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — ISBN 0-201-71594-5.