Почему шаблон проектирования метода фабрики полезнее, чем иметь классы и вызывать их по отдельности?

32

Из шаблонов проектирования «Банды четырех» есть метод Фабрики:

class Factory(product)
  case product
  when a
    new A
  when b
    new B
  when c
    new C
end

new Factory(a)

Почему это более полезно , чем иметь три класса, a, bи cи называя их по отдельности?

альт
источник
1
Что вы имеете в виду именно? Почему бы не создать экземпляр всех трех? Это то, что вы имели ввиду?
Нил
1
@Neil Нет, в шаблоне фабрики все классы существуют как братья и сестры. Зачем вызывать фабрику для косвенного доступа к классам a, b, c?
альт
3
это на самом деле не похоже на шаблон фабричного метода, во всяком случае, ближе к абстрактной фабрике
jk.
2
Потому что во время разработки вы не знаете, какой из 3 классов вам нужно создать.
MrWhite
2
@jk: нет, на самом деле это не так. programmers.stackexchange.com/questions/81838/…
pdr

Ответы:

54

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

Но если вам нужно знать больше, чем продукт для построения A, B или C, и вы не можете иметь прямой доступ к этим знаниям, тогда это полезно. Затем вы используете фабрику в качестве центра знаний для производства необходимых объектов.

Возможно, эти объекты нуждаются в ссылке на некоторый объект X, который может предоставить фабрика, но ваш код в том месте, где вы хотите построить A, B или C, не может или не должен иметь доступа к X. Может быть, когда у вас есть X вы создаете A и B, но если у вас есть тип Y, то вы создаете C.

Также учтите, что некоторым объектам может потребоваться 20 зависимостей для создания; что тогда? Поиск таких зависимостей в местах, где они не должны быть доступны, может быть проблематичным.

Матеуш
источник
13
+1 за разъяснение, что фабричный шаблон не всегда лучший подход.
Нил
1
Потому что ваш пример не достаточно сложен. Для такого простого сценария даже не имеет смысла использовать расширенный шаблон. Так что бы вы сделали в этом случае? Встроить условную конструкцию?
PSD
Это может быть просто метод, который берет продукт и возвращает то, что вам нужно, чтобы сделать его многоразовым, поэтому он не должен быть встроенным. Если такой метод перерастает во что-то большее или используется в нескольких других классах, вы можете переориентировать его на другой класс.
Матеуш
Шаблон называется фабричным методом по причине. Метод не должен быть в другом классе, чтобы быть фабричным методом (хотя это часто бывает).
PSD
Я пропустил «Метод» в этом, так что вы правы, мистер.
Матеуш
23

Заводской шаблон обычно более сложен, чем этот. Фабрика принимает решение по определенным критериям, какой экземпляр создать / вернуть. Вместо этого, когда вы не используете фабрику, этот код будет неоднократно использоваться в нескольких местах вашего кода.

В качестве примера рассмотрим следующее: вам нужно загрузить данные из БД, но у вас есть одна центральная БД для интеграции с большим количеством данных и одна меньшая в памяти на каждом dev-ПК. В своем коде вы просите завод , чтобы получить на DB-ручку и фабричные возвращается один из тех , в зависимости от того, например , файл конфигурации.

Энди
источник
20

Шаблон Factory Method абстрагирует процесс принятия решения от вызывающего класса. Это имеет несколько преимуществ:

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

Unit-Тестируемость. Я могу написать 3 теста для фабрики, чтобы убедиться, что она возвращает правильные типы при правильных условиях, тогда мой вызывающий класс должен быть проверен только на предмет того, вызывает ли он фабрику, а затем необходимые методы в возвращаемом классе. Ему не нужно ничего знать о реализации самой фабрики или конкретных классов.

Расширяемость. Когда кто-то решает, что нам нужно добавить новый класс D к этой фабрике, ни о каком вызывающем коде, ни о модульных тестах, ни о реализации никогда не нужно говорить. Мы просто создаем новый класс D и расширяем наш фабричный метод. Это само определение Открыто-Закрытого Принципа .

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

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

прецизионный самописец
источник
14

Ключевые преимущества фабричного шаблона двояки:

  1. Места, которые нуждаются в реализации продукта, не должны знать, как его создать. Фабрика хранит эту информацию.

    Хотите знать, какие аргументы передать конкретному конструктору? Или какие зависимости вы должны ввести? Или как зарегистрировать класс реализации в базе данных после того, как он полностью настроен? Нет? Пусть фабрика позаботится обо всем этом.

  2. Местам, где требуется реализация продукта, не нужно знать во время описания модуля (т. Е. Во время компиляции), как называется класс реализации.

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

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

Donal Fellows
источник
2

Я хотел бы думать о шаблонах проектирования в терминах «люди», а шаблоны - это способы общения людей друг с другом.

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

Поэтому, когда им нужен новый сотрудник, они звонят в агентство по найму и говорят им, что им нужно. Теперь, чтобы действительно нанять кого-то, вам нужно знать много вещей - льготы, подтверждение соответствия требованиям и т. Д. Но нанимающему персоналу не нужно ничего знать об этом - кадровое агентство все это обрабатывает.

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

учтивость

Premraj
источник
1

Шаблон «Фабрика» - это наиболее часто используемый шаблон дизайна.

Я сталкивался с многочисленными случаями, когда класс Factory закодирован, когда достаточно простого конструктора.

Не используйте фабричный класс, если:

  • Вы зависите от внешнего ресурса, но еще не знаете, какой именно.
  • Строительство стоит дорого, и вы хотите построить один раз и использовать много раз.
  • Создание нового экземпляра зависит от того, какие экземпляры уже созданы (например, у вас может быть только пять подключений, или вы должны использовать номер подключения на один номер больше, чем последний использованный номер).
Джеймс Андерсон
источник
0

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

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

Примером может быть наличие подклассов, где каждый сортирует данные в порядке возрастания, но по-своему. Каждый способ оптимален для определенного вида данных. Например: частично отсортированные данные, данные, которые являются числами и т. д. Код клиента - это класс, который обрабатывает только печать данных. Наличие кода, который решает, какой класс сортировки будет создан в клиентском классе, сделает его сложным классом. Другими словами, имея более чем одну ответственность, в этом случае решаем, какой класс сортировки является оптимальным, и печатаем данные. Помещая код, который решает, какой класс сортировки создается, в класс Factory, он разделяет проблемы, так что вам не нужно менять клиентский класс каждый раз, когда вам нужно изменить, какой подкласс сортировки создается.

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

kiwicomb123
источник