Где бы вы использовали шаблон Builder вместо абстрактной фабрики? - PullRequest
23 голосов
/ 22 декабря 2009

Я видел, как этот вопрос поднимался здесь и там несколько раз, но я так и не нашел и не ответил, что был доволен.

Из Википедии:

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

Но для клиента это не одно и то же? Он получает полный объект сразу после его создания, поэтому для него нет никакой дополнительной функциональности.

Единственный способ, которым я вижу это как способ или поэтапная организация кода конструктора, чтобы создать структуру для реализации компоновщиков. Что неплохо, но вряд ли это отличный шаг от абстрактной фабрики.


Этот следующий фрагмент из Википедии - хорошая ссылка, чтобы понять мою точку зрения:

Часто проекты начинаются с использования Factory Method (менее сложный, более настраиваемый, подклассы распространяются) и переходят к Abstract Factory, Prototype или Builder (более гибкие, более сложные), когда дизайнер обнаруживает, где требуется большая гибкость.

Если это так, какую сложность нужно было бы ввести в вашей системе, когда бы вы перешли с абстрактной фабрики на строителя?

Суть в том, что я не могу найти и пример, в котором ясно, что абстрактной фабрики будет недостаточно, и вместо этого вам понадобится строитель.

Ответы [ 10 ]

13 голосов
/ 22 декабря 2009

AbstractFactory для семейства сопутствующих товаров. Строитель для одного продукта.

Конструктор предназначен для поэтапного построения сложного продукта, а AbstractFactory - для абстрактного построения (т. Е. Один раз для нескольких реализаций) менее сложного продукта.


Примеры значения разницы для кода вызова:

  • Для клиентского кода, использующего AbstractFactory, каждый вызов метода создает один объект. Клиент должен собрать их вместе . С другой стороны, сборщик собирает их внутри и предоставляет полный граф объектов в качестве последнего шага здания.

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


ОБНОВЛЕНО в ответ на этот комментарий:

Lino> Хотя это все еще беспокоит меня :). Я имею в виду, если вы создаете составные объекты и вы берете директора, передавая ответственность за вызов методов построения клиентам, тогда это работает для меня. Только тогда застройщик показался бы идеальной подгонкой. Но с режиссером это не так уж и много ...

Точно, у Builder нет директора, он позволяет каждому клиенту создавать сложный продукт в соответствии с его конкретными потребностями . Клиент является директором, потому что реализация директора не используется повторно.

Если вам нужно несколько раз повторно использовать сложный процесс сборки, тогда у вас может быть метод для инкапсуляции этого (и этот метод является вашим «директором»).

Напротив, для AbstractFactory обычно требуется многократно используемый директор, который создает продукты (с реализацией Factory).

7 голосов
/ 22 декабря 2009

Здесь уже есть несколько очень хороших ответов. Я просто предлагаю аналогию.

Скажем, вы хотели новый стол для вашего нового офиса. Вы идете на «фабрику» и видите выбор, затем выбираете одну из полок. Если это соответствует вашим потребностям, отлично!

Теперь у вас большой офис с действительно причудливыми стенами. Теперь вам нужен стол с верхней частью в форме, подходящей для вашего офиса. И вы хотите, чтобы другие ножки подходили к остальной мебели, а также соответствовали вашему новому креслу Aeron.

Вы возвращаетесь на тот же завод, не повезло. Вы идете к плотнику, который может изготовить на заказ то, что вы хотите. Вы даете свои спецификации и требования, и «строитель» скажет вам определенные ограничения. После нескольких итераций вы получили идеальный стол!

Ладно, нехорошая история, но только для облегчения: P

4 голосов
/ 22 декабря 2009

Один хороший пример, когда вам нужен конструктор, - это если вы строите что-то по частям на основе аргументов командной строки. Например, рассмотрим конструктор с такими методами, как ...

setName()
setType()
setOption()

Строитель также может быть объединен с абстрактной фабрикой, где директор просит фабрику для конкретного продукта. Опять же, это можно сделать с помощью простого шаблона фабрики, передав список аргументов фабрике, но что делать, если вместо этого аргументы были сообщениями, поступающими с сервера или клиента.

Иногда эстетика одного рисунка просто лучше, чем эстетика другого.

2 голосов
/ 22 декабря 2009

Builder - это инверсия управления, как в Template Template Pattern. Различные функции вашего конкретного строителя являются настраиваемыми этапами процесса. Абстрактная Фабрика - это «просто» полиморфизм, где на выходе получается вновь построенный объект. Различные функции на конкретном заводе представляют собой различные настраиваемые процессы, каждый из которых, вероятно, приводит к отдельному объекту.

Итак, вам нужен строитель, когда вам нужен общий общий «сюжет» для построения ваших объектов, но отдельные «сцены» на этом графике отличаются. Вам нужна фабрика, когда между разными реализациями не обязательно есть что-то общее.

Я думаю, что вы могли бы использовать и то и другое одновременно: Абстрактная фабрика выступала в качестве директора в шаблоне Строителя, а каждая конкретная фабрика направляла вещи по-своему. Тем не менее, это выходит за пределы "салфетки" для диаграмм UML; -)

2 голосов
/ 22 декабря 2009

Builder полезен для настройки. Abstract Factory полезна, когда вы не хотите, чтобы вызывающие абоненты заботились о фактической реализации. Два разных назначения.

Вы могли бы фактически смешать два шаблона. Например, Java DocumentBuilderFactory - это классическая абстрактная фабрика: если вы прочитаете документы, вы увидите процесс, который он использует для выбора реализации. Тем не менее, DocumentBuilder , которые он производит, может быть сконфигурирован позднее (хотя они не следуют прототипному подходу «построителя», когда каждый метод конфигурации возвращает объект, который был сконфигурирован).

1 голос
/ 24 декабря 2009

Рассмотрим аналогию.

Вы находитесь в сети быстрого питания, где фаст-фуд, который вы на самом деле получаете, довольно сложен. Это не только сложно, но только определенные люди могут принять ваш заказ на определенные виды пищи. Теперь вы этого не знаете, потому что менеджер магазина решил оставить одного человека за одним кассовым аппаратом. Но если вы посмотрите на него внимательно, это на самом деле продвинутая голограмма, потому что она "абстрактная" . Абстрактный заказчик. Теперь, когда вы говорите с голограммой и размещаете свой заказ, компьютер с голограммой перенаправляет (полиморфизм) этот заказ на имплантат в мозг человека, принимающего заказ. Имплант заставляет человека на самом деле ударить в порядке реального регистра. Есть несколько таких 'конкретных' управляемых разумом людей, которые упорядочены голограммой. Теперь, когда настоящий человек наносит удары по порядку, он отправляется на задний компьютер, где есть сборочная линия, или «строитель» , для каждого типа производимой еды. Заказы отправляются на различные сборочные линии в зависимости от человека и его кассового аппарата.

Итак, голограмма - это абстрактная фабрика, контролируемые разумом люди на регистрах - это конкретные фабрики, а сборочные линии - строители. Таким образом, вы можете визуализировать поток абстрактной фабрики, работающей С по шаблону компоновщика. Иногда лучше посмотреть, как шаблоны проектирования работают вместе, чтобы увидеть, чем они отличаются.

Если вы ищете дополнительный кредит, попробуйте реализовать это с помощью дженериков. Это не требует столько кода, сколько вы думаете.

1 голос
/ 22 декабря 2009

Я использую Абстрактную Фабрику, когда мне нужно будет создать несколько дочерних фабрик для создания различных типов объектов. Все эти дочерние фабрики реализуют или расширяют Абстрактную Фабрику. Я использую Builder, когда нужно построить только один тип объекта.

Я не уверен, что это правильное использование, но это то, как я видел это, и как я делал это в прошлом.

0 голосов
/ 08 марта 2013

Хорошие ответы, я хотел бы добавить мои в надежде, что я понимаю, что мое понимание верно.

Если у вас новый офис, и вам нужны только новые столы, вы должны использовать Builder. Письменный стол всегда будет письменным столом, но существует множество различных конфигураций письменного стола, то есть его размер, форма, наличие клетки, ящиков и т. Д.

Если у вас новый офис, а внутренняя часть полностью пуста, вам потребуются различные объекты и вы будете использовать Абстрактную Фабрику, которая создает Мебель, из которой спускается наш Стол. В этом случае Desk, как мы знаем, является «сложным» объектом, поэтому он использует шаблон Builder, но здесь он является частью направляющей абстрактной фабрики. Абстрактная фабрика также создаст простые объекты, такие как очень специфические лампы (StraightFunkyLamp), через класс StraightFunkyLampFactory.

0 голосов
/ 28 января 2011

На практике вы, вероятно, будете использовать DI + IOC, чтобы делать то, что делал строитель. FYI.

0 голосов
/ 23 декабря 2009

Для получения дополнительной информации о , когда использовать шаблон Builder и его преимуществах , вы должны проверить мой пост для другого подобного вопроса здесь

...