Порождающие шаблоны / Фабричный метод
- Виртуальный конструктор (Virtual Constructor)
- Описание паттерна
- Реализация паттерна
- Примеры
- Использование
- Преимущества
- Недостатки
- Похожие паттерны
- Взаимодействие с другими паттернами
- Источники
Вы производите на заводе три вида машин: Маленькую
, Среднюю
и Большую
. Они очень похожи, но для работы им нужны разные моторы. В каком месте класса Машины нужно указать, какой мотор ей нужен?
Лучше, если создание мотора нужного типа будет вынесено в отдельный метод. Тогда вы легко сможете переопределить его у любого класса машины.
Фабричный метод выносится на самый верх иерархии классов (в родительский или абстрактный класс). То есть у класса есть некоторый метод, который производит объект, который нужен классу - Фабричный метод. Этот метод может быть абстрактным, чтобы каждый дочерний класс дал собственную реализацию или иметь некоторое дефолтное поведение (например, возвращать самый простой мотор).
Конкретная реализация фабричного метода предоставляется дочерними классами. Таким образом, каждый дочерний класс сам решает, какой именно объект создавать. МаленькаяМашина
создает себе МаленькийМотор
, а БольшаяМашина
- БольшойМотор
. При этом вся логика по выбору и созданию мотора находится в одном месте - в фабричном методе.
- Иерархия создателей:
- Родительский класс
Creator
определяет фабричный метод для создания объектаFactoryMethod()
. - Конкретные создатели
ConcreteCreator
реализуют этот метод по-своему.
- Родительский класс
- Иерархия продуктов:
- Порождаемые классы (продукты) тоже объединяются в отдельную иерархию, ведь они являются родственными и должны иметь одинаковый интерфейс. Класс
Product
предоставляет общий интерфейс продукта. - Классы
ConcreteProduct
определяют конкретные продукты.
- Порождаемые классы (продукты) тоже объединяются в отдельную иерархию, ведь они являются родственными и должны иметь одинаковый интерфейс. Класс
- Каждый
КонкретныйСоздатель
в своей реализацииФабричногоМетода
создает тотКонкретныйПродукт
, который ему нужен.
Как именно создается Продукт
не имеет значения. Это может быть обычное создание нового объекта через конструктор, или получение объекта из некоторого хранилища, или переиспользование другого объекта.
Важно:
- Продукты имеют одинаковый интерфейс.
- Фабричный метод возвращает Продукт или объект с интерфейсом Продукта.
- Фабричный метод - лишь один из методов Создателя, которых может быть много.
Не важно:
- Логика создания/получения
Продукта
внутри фабричного метода.
Чтобы добавить поддержку нового Продукта
, нужно создать новый подкласс Создателя
и реализовать у него соответствующий фабричный метод.
- Неизвестно заранее, с каким типом объектов придется работать коду. Вынесение создания Продукта в отдельный метод позволяет легче им управлять.
- Нужна возможность расширения иерархии создателей. Например, вы создаете еще один тип машины - Трактор. Чтобы дать ему правильный мотор, нужно только реализовать фабричный метод класса.
- Абстрагирует создание продукта, убирает лишние привязанности.
- Упрощает поддержку кода создания продукта.
- Упрощает добавление новых продуктов и создателей.
- Позволяет расширять и усложнять логику создания/переиспользования продуктов.
- Иерархии создателей и продуктов быстро разрастаются.
- Для каждого нового типа Продукта нужен свой Создатель.
- Строитель (Builder). Фабрика с более тонкой настройкой
- Абстрактная фабрика (Abstract Factory). Фабрика фабрик
- Прототип (Prototype). Создание объектов через копирование
При усложнении паттерн Фабричный метод
обычно следует заменить одним из этих паттернов. Например, если в системе много продуктов, которые создаются Фабричным методом, имеет смысл создать отдельную Фабрику
для их прозводства. Такая Фабрика может иметь несколько методов, каждый из которых является фабричным и производит определенный продукт. Если у вас есть несколько наборов продуктов (например, в разных стилях), можно создать несколько таких Фабрик
. Для управления ими используйте паттерн Абстрактная фабрика
.
Использование паттерна в структуре другого паттерна (один паттерн является частью другого)
- Абстрактная фабрика (Abstract Factory). Использует
Фабричный метод
для непосредственного создания классов. - Шаблонный метод (Template).
Фабричный метод
- частный случайШаблонного метода
.
Способы реализации паттерна (вариации механизмов работы паттерна)
- Приспособленец (Flyweight). Позволяет повторно использовать уже существующие объекты, а не создавать их заново.
Частое применение (паттерны не связаны напрямую)
- Итератор (Iterator). Итераторы выступают в качестве продуктов, разным подклассам требуются разные итераторы.