29.08 2010

Builder

Перед прочтением ознакомьтесь с введением в паттерны проектирования на PHP, в котором описаны принятые соглашения и понятия. Данная статья дополняется с некоторой периодичностью, так что если вы ее читали ранее, не факт что данные не изменились.

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

Пример

Вернемся к нашему примеру с игрой. Предположим нам нужно получить объект "казармы", который различен для каждой расы. Причем различия настолько велики, что мы не можем использовать единый интерфейс для них (или общий родительский класс), а значит мы не можем использовать абстрактную фабрику. При этом нам очень важно, чтобы создание объекта казарма проходила для всех рас одинаково. В таком случае, нам поможет паттерн строитель.

Суть паттерна

UML

Вы этой схеме, director - это распорядитель, которому назначается строитель (builder), который и будет занимать конструированием объекта. При этом от клиента будет скрыт сам процесс создания, но известен результат.

Реализация на PHP

// Распорядители могут быть разные, но они должны соответствовать одному интерфейсу,
// в этом примере - интерфейсу класса Director_Abstract

abstract class Director_Abstract
{
    protected
        $Builder = null;

    public function __construct(Builder_Abstract $Builder)
    {
        $this -> Builder = $Builder;
    }

    public function construct()
    {
        $this -> Builder -> BuildPartA();
        $this -> Builder -> BuildPartB();
    }
}

class Director extends Director_Abstract {}

/**
 * Все строители должны соответствовать единому интерфейсу
 */

abstract class Builder_Abstract
{
    public function BuildPartA() {}
    public function BuildPartB() {}
    abstract public function getResult();
}

class Builder extends Builder_Abstract
{
    protected
        $Product = null;

    public function __construct()
    {
        $this -> Product = new Product();
    }

    public function BuildPartA()
    {
        //do something
    }

    public function BuildPartB()
    {
        //do something else
    }

    public function getResult()
    {
        return $this -> Product;
    }
}

class Product {}

$Builder = new Builder();
$Director = new Director($Builder);
$Director -> construct();

$Product = $Builder -> getResult();

Скачать пример можно тут

  • В этом примере мы передаем объект "строитель" в конструктор распорядителя, однако такой подход не всегда удобен. Если с помощью этого распорядителя планируется создавать множество объектов различными строителями, то лучше ввести метод setBuilder.

  • В абстрактном классе Builder_Abstract, методы BuildPartA и BuildPartB намерено сделаны пустыми, а не абстрактными. Это позволяет конкретным строителям реализовывать только те методы, которые им необходимы для конструирования продукта.

  • Так как php является языком со слабой типизацией, то можно обойтись без метода getResult и возвращать результат из метода construct.

  • Паттерн абстрактная фабрика во многом схож со строителем, так как так же позволяет конструировать сложные объекты, с тем лишь отличием, что абстрактная фабрика заточена на создании семейств объектов (простых и сложных), в то время как строитель делает акцент на пошаговом создании объекта.

  • Паттерн компоновщик - зачастую является результатом работы паттерна строитель

comments powered by Disqus