Будівельник (шаблон проєктування)Будівельник (англ. 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Приклад реалізації мовою 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 Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — ISBN 0-201-71594-5.
|