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

Предлагается, чтобы разработчики заменили создание объектов с помощью
оператора constructor или с помощью оператора new. Это звучит странно, но объект будет создан с использованием только constructor, который вызывается внутри фабричного метода.

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

Давайте разберемся на примере

Постановка задачи

Представьте, что вы хотите добавить различное поведение ведения журнала для разных сред приложений, например Production, Development, Test и Debug.

  • В Production: отображается только loglevel=error|warn.
  • В Development: отображаются все loglevel=info|error|warn|debug.
  • В : должно отображаться только loglevel=debug.

Для простоты давайте работать только с двумя средами, т. е. Production и Development.

Реализация без использования шаблона

Реализация Logger включает в себя так много if-else или ' if (то же самое можно выполнить с помощью switch).

Представьте себе будущее

  • Добавлено какое-то новое окружение, скажем, Cloud. Так что это приносит с собой новые проблемы и условия.
  • Заставить разработчика изменить реализацию класса Logger.
  • Обновление условия в соответствии с ним
  • Изменены бизнес-правила для логгера

Таким образом, эту реализацию невозможно обслуживать, и она подвержена нежелательному поведению.

Реализация фабричного метода

Разработчик создает абстракцию или интерфейс с именем Logger и предоставляет конкретную реализацию для различных подклассов общего суперкласса Logger для различных сред, то есть ProductionLogger, DevelopmentLogger, TestingLogger и DebugLogger.

Таким образом, каждый метод подкласса Logger должен содержать свою реализацию и бизнес-правила.

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

Для тех, кто не понимает диаграмму UML, на ней показано отношение IS-A между абстрактным классом Logger и подклассами (DevelopmentLogger, TestingLogger и т. д.), так что DevelopmentLogger является Logger.

Разработчик создает файл interface с именем ILoggerBuilder. Это отвечает за предоставление объекта правильного типа Logger в соответствии с требованием или некоторой логикой. Диаграмма UML показывает отношение IS-A между абстрактным классом Logger и подклассами (DevelopmentLogger, TestingLogger и т. д.), так что DevelopmentLogger является Logger.

Разработчик создает interface с именем ILoggerFactory. Это отвечает за предоставление объекта правильного типа Logger в соответствии с требованием или некоторой логикой.

EnvironmentLoggerFactory реализует ILoggerFactory, который отвечает за создание соответствующего объекта подкласса Logger в соответствии со средой, в которой выполняется приложение, или, скажем, существует сложная логика для создания некоторого объекта;

Давайте напишем псевдокод

Теперь разработчик добавляет EnvironmentLoggerFactory, который реализует ILoggerFactory

Реализация регистратора

Снова представьте будущее

  • Добавляется какая-то новая среда, скажем, Cloud.
  • РЕШЕНИЕ. Теперь разработчик должен разработать новый подкласс CloudLogger, наследующий Logger.
  • Правила можно внедрять, не думая, что они сломаются в среде разработки или производства.
  • Изменены бизнес-правила для логгера, например, все логи в облаке должны храниться в базе данных

Применимость

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

Общая реализация шаблона

  1. Все продукты должны быть унаследованы или реализованыProduct
  2. Добавьте фабричный метод внутри CreatorFactory, который всегда возвращает объект базового типа Product.
  3. Замените все вызовы конструктора в коде фабричным методом.

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

Преимущества

  1. Избегайте тесной связи
  2. Основной принцип с единой ответственностью, поэтому весь код создания объектов разделен, что упрощает управление кодом.
  3. Open/Close Principal, разработчик может представить новый продукт в соответствии с изменениями, не нарушая код клиента.

Заключение

Фабричный метод — это мощный способ создания сложных объектов; он продвигает слабую связанность, принцип единой ответственности и принцип открытия/закрытия.

Следуйте за мной на GitHub

Чтобы узнать больше об этом паттерне, посмотрите это видео Кристофера Охрави.