Builder (Строитель)

Паттерн проектирования Active Record

Паттерн проектирования 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();
?>