Строитель (Builder)
реализации: java, количество: 6
реализации(исходники)
+добавить
Строитель – паттерн, конструирующий, собирающий объект. codelab.ru codelab.ru оригинал источник
Условия, Задача, Назначение
Отделяет конструирование сложного объекта от его модели, т.е содержания и представления. codelab.ru codelab.ru источник оригиналПодробней. Есть клиент, которому часто нужно создавать различные, сложные объекты. При этом процесс создания всех этих объектов – протекает очень схожими этапами, так что можно очертить общий единый алгоритм, включающий выполнение всех возможных действий, которые только могут потребоваться для построения всех сложных объектов.
При этом важный момент – конструируемые сложные объекты в общем случае не схожи между собой, т.е. невозможно разумным образом как-то обобщить все эти создаваемые объекты в единую иерархию, объединить общие свойства и т.д. Более того – на самом деле, это и не нужно делать! В смысле – это никому не нужно: клиент всегда знает где, в каком месте и какой ему нужно создать объект и нет необходимости что-то унифицировать.
Таким образом, получаем: различные, сложные объекты, которые нужно создавать на разных этапах и фазах выполнения приложения, а также довольно схожие алгоритмы их конструирования. Поэтому, чтобы не дублировать похожие места кода создания объектов – было бы очень удобно объединить этот процесс в единый алгоритм (Director, распорядитель), способный создать любой из интересующих сложных объектов.
Дальше – т.к. объекты совершенно разные – необходимо чтобы каждый объект имел свое конкретное внутреннее представление (структуру), т.к. невозможно создать все эти объекты с одинаковым внутреннем представлением. И вот уже для этого – следует выделить еще одну сущность (Builder, строитель), отвечающую непосредственно уже за создание отдельных частей объекта. Эта сущность будет своя на каждый сложный объект, который может быть построен.
Мотивация
Для небольшого примера рассмотрим кодировщик, в который заложена возможность распознавания и чтения документа в формате RTF (RichTextFormat), должна также «уметь» преобразовывать его во многие другие форматы, например в простой ASCII-текст или в представление, которое можно отобразить в виджете для ввода текста. Однако число вероятных преобразований заранее неизвестно. Поэтому должна быть обеспечена возможность без труда добавлять новый конвертор. источник codelab.ru codelab.ru оригинал
оригинал codelab.ru источник codelab.ru
Признаки применения, использования паттерна Строитель (Builder)
Если: источник codelab.ru codelab.ru оригинал- Алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект, и как они стыкуются между собой. codelab.ru оригинал codelab.ru источник
- Процесс конструирования должен позволять создавать различные представления результирующего объекта. codelab.ru оригинал codelab.ru источник
Решение
источник оригинал codelab.ru codelab.ru
источник codelab.ru оригинал codelab.ru
Участники паттерна Строитель (Builder)
источник codelab.ru оригинал codelab.ru- Builder (TextConverter) – строитель, абстрактный класс.
Содержит перечень всех возможных абстрактных методов для создания и стыковки частей различных объектов (продуктов). codelab.ru источник оригинал codelab.ru - ConcreteBuilder (ASCIIConverter,TeXConverter,TextWidgetConverter) – конкретный строитель, занимающийся созданием какого-либо одного объекта (продукта).
Конструирует и связывает вместе части продукта посредством реализации только тех абстракных методов интерфейса Builder, которые нужны для создания частей этого продукта. Кроме этого – определяет внутреннее представление этого сложного объекта и предоставляет интерфейс для его получения: GetASCIIText, GetTextWidget. codelab.ru оригинал codelab.ru источник - Director (RTFReader) – распорядитель.
Фиксированный, единый алгоритм создания любых продуктов, для которых имеется соответствующий Builder. Конструирует продукт пользуясь общим интерфейсом Builder-а. codelab.ru оригинал codelab.ru источник - Product (ASCIIText, TeXText, TextWidget) – конечный продукт, построенный с помощью конкретного Builder-а.
Представляет сложный конструируемый объект. ConcreteBuilder строит внутреннее представление продукта и определяет процесс его сборки. Помимо этого может включать классы, которые определяют составные части, в том числе интерфейсы для сборки конечного результата из частей. codelab.ru источник codelab.ru оригинал
Схема использования паттерна Строитель (Builder)
источник codelab.ru оригинал codelab.ru- Клиент создает объект-распорядитель Director и конфигурирует его нужным объектом-строителем Builder источник оригинал codelab.ru codelab.ru
- Распорядитель уведомляет строителя о том, что нужно построить очередную часть продукта источник оригинал codelab.ru codelab.ru
- Строитель обрабатывает запросы распорядителя и добавляет новые части к продукту источник оригинал codelab.ru codelab.ru
- Клиент забирает продукт у строителя оригинал codelab.ru источник codelab.ru
источник оригинал codelab.ru codelab.ru
Вопросы, касающиеся реализации паттерна Строитель (Builder)
Обычно существует абстрактный класс Builder, в котором определены операции для каждого компонента, который распорядитель может «попросить» создать. источник codelab.ru codelab.ru оригинал- Интерфейсы сборки и конструирования.
Строители конструируют свои продукты шаг за шагом. Поэтому интерфейс класса Builder должен быть достаточно общим, чтобы обеспечить конструирование при любом виде конкретного строителя.
Ключевой вопрос проектирования связан с выбором модели процесса конструирования и сборки. Обычно бывает достаточно модели, в которой результаты выполнения запросов на конструирование просто добавляются к продукту. В примере с RTF-документами строитель преобразует и добавляет очередную лексему к уже конвертированному тексту. оригинал codelab.ru codelab.ru источник - Почему нет абстрактного класса для продуктов?
В типичном случае продукты, изготавливаемые различными строителями, имеют настолько разные представления, что изобретение для них общего родительского класса ничего не дает. В примере с RTF-документами трудно представить себе общий интерфейс у объектов ASCIIText и TextWidget, да он и не нужен. codelab.ru codelab.ru источник оригинал - Поскольку клиент обычно конфигурирует распорядителя подходящим конкретным строителем, то, надо полагать, ему известно, какой именно подкласс класса Builder используется и как нужно обращаться с произведенными продуктами. codelab.ru оригинал источник codelab.ru
- Позволяет задавать разное внутреннее представление продукта.
Объект Director оперирует лишь абстрактным интерфейсом класса Builder для создания сложного продукта по его частям. За этим абстрактным интерфейсом может быть скрыто, в принципе, какое угодно внутреннее представление объекта. Как следствие – для изменения этого внутреннего представления, нужно лишь определить новый вид строителя. оригинал codelab.ru источник codelab.ru - Отделяет процесс конструирования объектов от процесса создания их внутреннего представления.
Паттерн строитель улучшает модульность, инкапсулируя способ конструирования и представления сложного объекта. Клиентам ничего не надо знать о классах, определяющих внутреннюю структуру продукта, они отсутствуют в интерфейсе строителя.
Каждый конкретный строитель ConcreteBuilder содержит весь код, необходимый для создания и сборки конкретного вида продукта. Код пишется только один раз, после чего разные распорядители могут использовать его повторно для построения вариантов продукта из одних и тех же частей.
В примере с RTF-документом мы могли бы определить загрузчик для формата, отличного от RTF, скажем, SGMLReader, и воспользоваться теми же самыми классами TextConverters для генерирования представлений SGML-документов в виде ASCII-текста, ТеХ-текста или текстового виджета. источник codelab.ru оригинал codelab.ru - Дает полный, более тонкий контроль над процессом конструирования.
В отличие от порождающих паттернов, которые сразу конструируют весь объект целиком, строитель делает это шаг за шагом под управлением распорядителя. И лишь когда продукт завершен, распорядитель забирает его у строителя. Поэтому интерфейс строителя в большей степени отражает процесс конструирования продукта, нежели другие порождающие паттерны. Это позволяет обеспечить более тонкий контроль над процессом конструирования, а значит, и над внутренней структурой готового продукта. оригинал codelab.ru источник codelab.ru
Пример
Рассмотрим реализацию сборочного конвейера автомобилей. Как известно по нему двигается сначала пустой кузов (каркас), и постепенно на каждом новом этапе к этому каркасу дособираются новые части. В общем случае на конвейере, в принципе, все-равно что собирать – грузовики, легковые и т.д.; главное чтобы соответствующие рабочие бригады выполняли свою работу последовательно на каждом этапе. codelab.ru codelab.ru источник оригиналПоэтому последовательность наших действий, выполняемых конвейером(ProductionLine) может быть очень просто сведена к определенному всегда одинаковому сценарию: сборка, добавление дверей в авто, колес, двигателя и покраска (метод MakeCar()): ProductionLine.java codelab.ru источник codelab.ru оригинал
Соответственно, получим строитель, дающий возможность выполнять все эти действия: CarBuilder. оригинал источник codelab.ru codelab.ru
Теперь просто смотрим, какие авто нам нужно будет собирать и реализуем соответствующие строители. К счастью в данной ситуации нам нужны лишь «Десятки» и «КамАЗы», поэтому добавляем только: Vaz2110Builder, KamazBuilder. codelab.ru источник codelab.ru оригинал
Реализации: java(6) +добавить реализацию
1) Client.java, code #419[автор:this]
2) ProductionLine.java, code #414[автор:this]
3) CarBuilder.java, code #415[автор:this]
4) Vaz2110Builder.java, code #416[автор:this]
5) KamazBuilder.java, code #417[автор:this]
6) RotatingPartCountBuilder.java, code #418[автор:this]



