Назначение: отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления.
Задача. Программа, в которую заложена возможность распознавания и чтения документа в формате RTF (Rich Text Format), должна также уметь преобразовывать его во многие другие форматы, например в простой ASCII-текст пли в формат LaTeX. Однако число вероятных преобразований заранее неизвестно. Поэтому должна быть обеспечена возможность без труда добавлять новый конвертор.
Решение. Паттерн Строитель предлагает конфигурировать класс RTFReader, отвечающий непосредственно за работу с документами в формате RTF, специальным объектом Converter, который будет преобразовывать RTF в другой текстовый формат. При разборе документа класс RTFReader вызывает Converter для выполнения преобразования. Всякий раз, когда RTFReader распознает лексему RTF (простой текст или управляющее слово), для ее преобразования объекту Converter посылается запрос. Объекты Converter отвечают как за преобразование данных, так и за представление лексемы в конкретном формате.
Подклассы Converter специализируются на различных преобразованиях и форматах. Например, ASCIIConverter игнорирует запросы на преобразование чего бы то ни было, кроме простого текста. С другой стороны, LaTeXConverter будет реализовывать все запросы для получения представления в формате LaTeX, собирая по ходу необходимую информацию о стилях.
Класс каждого конвертора принимает механизм создания и сборки сложного объекта и скрывает его за абстрактным интерфейсом. Конвертор отделен от загрузчика, который отвечает за синтаксический разбор RTF-документа. В паттерне Строитель абстрагированы все эти отношения. В нем любой класс конвертора называется строителем, а загрузчик – распорядителем. В применении к рассмотренному примеру Строитель отделяет алгоритм интерпретации формата текста (то есть анализатор RTF-документов) от того, как создается и представляется документ в преобразованном формате. Это позволяет повторно использовать алгоритм разбора, реализованный в RTFReader, для создания разных текстовых представлений RTF-документов; достаточно передать в RTFReader различные подклассы класса Converter.
Общая структура решения.
Builder (Converter) – строитель: задает абстрактный интерфейс для создания частей объекта Product.
ConcreteBuilder (ASCIIConverter, LaTeXConverter) – конкретный строитель: конструирует и собирает вместе части продукта посредством реализации интерфейса Builder; определяет создаваемое представление и следит за ним; предоставляет интерфейс для доступа к продукту (например, GetASCIIText, GetLaTeXText).
Director (RTFReader) – распорядитель: конструирует объект, пользуясь интерфейсом Builder.
Product (ASCIIText, LaTeXText) – продукт: представляет сложный конструируемый объект. ConcreteBuilder строит внутреннее представление продукта и определяет процесс его сборки; включает классы, которые определяют составные части, в том числе интерфейсы для сборки конечного результата из частей.
Клиент создает объект-распорядитель Director и конфигурирует его нужным объектом-строителем Builder. Распорядитель уведомляет строителя о том, что нужно построить очередную часть продукта. Строитель обрабатывает запросы распорядителя и добавляет новые части к продукту. Клиент забирает продукт у строителя. Диаграмма взаимодействий иллюстрирует взаимоотношения строителя и распорядителя с клиентом.
Применимость. Используйте паттерн Строитель, когда:
Результаты:
Особенности реализации. Обычно существует абстрактный класс Builder, в котором определены операции для каждого компонента, который распорядитель может «попросить» создать. По умолчанию эти операции ничего не делают. Но в классе конкретного строителя ConcreteBuilder они замещены для тех компонентов, в создании которых он принимает участие.
Вот еще некоторые моменты, связанные с реализацией:
Родственные паттерны.
Абстрактная Фабрика похожа на Строитель в том смысле, что может конструировать сложные объекты. Основное различие между ними в том, что Строитель делает акцент на пошаговом конструировании объекта, а Абстрактная Фабрика – на создании семейств объектов. Строитель возвращает продукт на последнем шаге, тогда как с точки зрения Абстрактной Фабрики продукт возвращается немедленно.
Паттерн Компоновщик – это то, что часто создает Строитель.