← Назад к вопросам

Что такое паттерн Фабричный метод?

1.8 Middle🔥 191 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

📖 Общее определение

Паттерн Фабричный метод (Factory Method) — это порождающий паттерн проектирования, который определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов. Он инкапсулирует логику создания объектов, делегируя её подклассам, что способствует соблюдению принципа открытости/закрытости (Open/Closed Principle).

🎯 Основная идея и проблема

Главная проблема, которую решает Factory Method — необходимость создавать объекты, не привязывая код к конкретным классам. Вместо прямого вызова конструктора (SomeClass()), мы используем специальный фабричный метод, который возвращает нужный экземпляр.

Классическая аналогия из iOS: Представьте, что ваш ViewController должен отобразить разные типы ячеек таблицы (UITableViewCell) в зависимости от типа контента. Прямое создание ячеек в методе cellForRowAt приводит к нагромождению условной логики и нарушению SRP. Фабричный метод выносит эту логику в отдельный компонент.

🔧 Ключевые компоненты паттерна

  1. Продукт (Product) — общий интерфейс или базовый класс для объектов, которые будет создавать фабрика.
  2. Конкретные продукты (Concrete Products) — реализации интерфейса Product.
  3. Создатель (Creator) — базовый класс (или протокол), объявляющий фабричный метод, возвращающий объект типа Product. Он может содержать и бизнес-логику, связанную с продуктами.
  4. Конкретные создатели (Concrete Creators) — переопределяют фабричный метод, чтобы возвращать конкретный экземпляр ConcreteProduct.

📱 Пример на Swift (UIKit)

Рассмотрим реальный кейс: создание алертов в разных стилях.

1. Определяем "Продукты" — типы алертов

// Базовый протокол для продукта
protocol AlertView {
    func show()
}

// Конкретные продукты
class SuccessAlert: AlertView {
    let message: String
    init(message: String) { self.message = message }
    func show() { print("✅ Success: \(message)") }
}

class ErrorAlert: AlertView {
    let message: String
    init(message: String) { self.message = message }
    func show() { print("❌ Error: \(message)") }
}

class LoadingAlert: AlertView {
    let message: String
    init(message: String) { self.message = message }
    func show() { print("⏳ Loading: \(message)") }
}

2. Создаем "Создателя" с фабричным методом

// Базовый создатель (может быть классом или протоколом)
protocol AlertFactory {
    // ФАБРИЧНЫЙ МЕТОД (может иметь параметры)
    func createAlert(message: String) -> AlertView

    // Дополнительная бизнес-логика, использующая продукт
    func presentAlert(message: String)
}

// Расширение с реализацией логики по умолчанию
extension AlertFactory {
    func presentAlert(message: String) {
        let alert = createAlert(message: message)
        alert.show()
        // Здесь может быть вызов UIViewController.present() и т.д.
    }
}

3. Реализуем "Конкретных создателей"

// Конкретные фабрики
class SuccessAlertFactory: AlertFactory {
    // Каждая фабрика определяет СВОЮ реализацию фабричного метода
    func createAlert(message: String) -> AlertView {
        return SuccessAlert(message: message)
    }
}

class ErrorAlertFactory: AlertFactory {
    func createAlert(message: String) -> AlertView {
        return ErrorAlert(message: message)
    }
}

class LoadingAlertFactory: AlertFactory {
    func createAlert(message: String) -> AlertView {
        return LoadingAlert(message: message)
    }
}

4. Использование в клиентском коде

class ViewController {
    var alertFactory: AlertFactory!

    func userDidLogin() {
        alertFactory = SuccessAlertFactory()
        alertFactory.presentAlert(message: "Login successful!")
        // Выведет: ✅ Success: Login successful!
    }

    func dataLoadingFailed() {
        alertFactory = ErrorAlertFactory()
        alertFactory.presentAlert(message: "Network error")
        // Выведет: ❌ Error: Network error
    }
}

✅ Преимущества использования

  • Избегание жесткой привязки: Клиентский код работает с интерфейсом AlertView, а не с конкретными классами.
  • Принцип единственной ответственности (SRP): Код создания объекта переносится в одно место, упрощая поддержку.
  • Принцип открытости/закрытости (OCP): Вы можете добавлять новые типы алертов (новые ConcreteProduct) и новые фабрики, не изменяя существующий клиентский код.
  • Упрощение тестирования: Фабрику легко подменить мок-объектом в unit-тестах.
  • Читаемость: Инициализация сложных объектов с множеством параметров инкапсулирована.

⚠️ Когда применять (и когда нет)

Используйте Factory Method, когда:

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

Рассмотрите другие варианты (Abstract Factory, Builder), когда:

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

🆚 Отличие от Абстрактной фабрики (Abstract Factory)

Частая путаница! Фабричный метод — это один метод, создающий один тип продукта. Абстрактная фабрика — это набор фабричных методов, создающих семейство связанных продуктов. Если упростить: Factory Method использует наследование, Abstract Factory — композицию.

Factory Method в iOS SDK можно увидеть в таких примерах, как UICollectionViewCell с методом register(_:forCellWithReuseIdentifier:) и последующим созданием через dequeueReusableCell(withReuseIdentifier:for:). Система выступает в роли Creator, а ваш зарегистрированный класс клетки — Concrete Product.

Таким образом, паттерн Фабричный метод — это мощный и элегантный инструмент для повышения гибкости, тестируемости и чистоты кода, который активно применяется в iOS-разработке для управления жизненным циклом объектов.

Что такое паттерн Фабричный метод? | PrepBro