Builder (Строитель)
Паттерн проектирования Builder
Описание Builder
Строитель (англ. Builder) — порождающий шаблон проектирования предоставляет способ создания составного объекта.
Отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления.
Применение:
- алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой;
- процесс конструирования должен обеспечивать различные представления конструируемого объекта.
Плюсы:
- позволяет изменять внутреннее представление продукта;
- изолирует код, реализующий конструирование и представление;
- дает более тонкий контроль над процессом конструирования.
Примеры реализации
// Builder Pattern in JavaScript
class Product {
constructor() {
this.parts = [];
}
addPart(part) {
this.parts.push(part);
}
listParts() {
console.log(`Product parts: ${this.parts.join(', ')}`);
}
}
class Builder {
constructor() {
this.product = new Product();
}
buildPartA() {
this.product.addPart('Part A');
return this;
}
buildPartB() {
this.product.addPart('Part B');
return this;
}
buildPartC() {
this.product.addPart('Part C');
return this;
}
getResult() {
return this.product;
}
}
// Usage
const builder = new Builder();
const product = builder
.buildPartA()
.buildPartB()
.buildPartC()
.getResult();
product.listParts();
// Builder Pattern in C++
#include <iostream>
#include <vector>
#include <string>
class Product {
private:
std::vector<std::string> parts;
public:
void addPart(const std::string& part) {
parts.push_back(part);
}
void listParts() const {
std::cout << "Product parts: ";
for (size_t i = 0; i < parts.size(); ++i) {
std::cout << parts[i];
if (i < parts.size() - 1) std::cout << ", ";
}
std::cout << std::endl;
}
};
class Builder {
protected:
Product* product;
public:
virtual ~Builder() = default;
virtual void buildPartA() = 0;
virtual void buildPartB() = 0;
virtual void buildPartC() = 0;
virtual Product* getResult() = 0;
};
class ConcreteBuilder : public Builder {
public:
ConcreteBuilder() {
product = new Product();
}
void buildPartA() override {
product->addPart("Part A");
}
void buildPartB() override {
product->addPart("Part B");
}
void buildPartC() override {
product->addPart("Part C");
}
Product* getResult() override {
return product;
}
};
// Builder Pattern in Go
package main
import "fmt"
type Product struct {
parts []string
}
func (p *Product) AddPart(part string) {
p.parts = append(p.parts, part)
}
func (p *Product) ListParts() {
fmt.Printf("Product parts: %v\n", p.parts)
}
type Builder interface {
BuildPartA()
BuildPartB()
BuildPartC()
GetResult() *Product
}
type ConcreteBuilder struct {
product *Product
}
func NewConcreteBuilder() *ConcreteBuilder {
return &ConcreteBuilder{
product: &Product{},
}
}
func (b *ConcreteBuilder) BuildPartA() {
b.product.AddPart("Part A")
}
func (b *ConcreteBuilder) BuildPartB() {
b.product.AddPart("Part B")
}
func (b *ConcreteBuilder) BuildPartC() {
b.product.AddPart("Part C")
}
func (b *ConcreteBuilder) GetResult() *Product {
return b.product
}
// Usage
func main() {
builder := NewConcreteBuilder()
product := builder.
BuildPartA().
BuildPartB().
BuildPartC().
GetResult()
product.ListParts()
}
# Builder Pattern in Python
from abc import ABC, abstractmethod
class Product:
def __init__(self):
self.parts = []
def add_part(self, part):
self.parts.append(part)
def list_parts(self):
print(f"Product parts: {', '.join(self.parts)}")
class Builder(ABC):
@abstractmethod
def build_part_a(self):
pass
@abstractmethod
def build_part_b(self):
pass
@abstractmethod
def build_part_c(self):
pass
@abstractmethod
def get_result(self):
pass
class ConcreteBuilder(Builder):
def __init__(self):
self.product = Product()
def build_part_a(self):
self.product.add_part("Part A")
return self
def build_part_b(self):
self.product.add_part("Part B")
return self
def build_part_c(self):
self.product.add_part("Part C")
return self
def get_result(self):
return self.product
# Usage
if __name__ == "__main__":
builder = ConcreteBuilder()
product = (builder
.build_part_a()
.build_part_b()
.build_part_c()
.get_result())
product.list_parts()
<?php
// Builder Pattern in PHP
class Product {
private $parts = [];
public function addPart($part) {
$this->parts[] = $part;
}
public function listParts() {
echo "Product parts: " . implode(', ', $this->parts) . "\n";
}
}
abstract class Builder {
protected $product;
abstract public function buildPartA();
abstract public function buildPartB();
abstract public function buildPartC();
abstract public function getResult();
}
class ConcreteBuilder extends Builder {
public function __construct() {
$this->product = new Product();
}
public function buildPartA() {
$this->product->addPart("Part A");
return $this;
}
public function buildPartB() {
$this->product->addPart("Part B");
return $this;
}
public function buildPartC() {
$this->product->addPart("Part C");
return $this;
}
public function getResult() {
return $this->product;
}
}
// Usage
$builder = new ConcreteBuilder();
$product = $builder
->buildPartA()
->buildPartB()
->buildPartC()
->getResult();
$product->listParts();
?>