Какие паттерны проектирования вы знаете и применяли на практике?

«Какие паттерны проектирования вы знаете и применяли на практике?» — вопрос из категории Паттерны, который задают на 33% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Паттерны проектирования — это типовые решения распространенных проблем. Я разделяю их на три классические категории и привожу примеры использования в iOS/macOS разработке.

1. Порождающие (Creational)

Управляют процессом создания объектов.

  • Singleton (Одиночка): Гарантирует наличие единственного экземпляра класса. Используется осторожно, преимущественно для stateless-менеджеров.
    class AppSettings {
        static let shared = AppSettings()
        private init() {}
        var isDarkMode: Bool = false
    }
  • Factory Method (Фабричный метод): Определяет интерфейс для создания объекта, но позволяет подклассам изменять тип создаваемого объекта.
  • Builder (Строитель): Позволяет создавать сложные объекты пошагово, отделяя конструирование от представления.

2. Структурные (Structural)

Определяют, как комбинировать классы и объекты в более крупные структуры.

  • Adapter (Адаптер): Позволяет объектам с несовместимыми интерфейсами работать вместе. Часто используется при интеграции сторонних сервисов.
  • Decorator (Декоратор): Динамически добавляет объекту новые обязанности. В Swift реализуется через расширения (extensions) и композицию.
  • Facade (Фасад): Представляет простой интерфейс к сложной подсистеме (например, фасад для сетевого слоя).

3. Поведенческие (Behavioral)

Решают задачи эффективного взаимодействия объектов и распределения ответственности.

  • Observer (Наблюдатель): Позволяет объектам уведомлять другие объекты об изменениях своего состояния. Реализации: NotificationCenter, KVO, @Published в Combine.
  • Delegate (Делегат): Объект поручает другому объекту (делегату) выполнение определенных задач. Краеугольный камень многих Cocoa Touch API (UITableViewDelegate).
  • Strategy (Стратегия): Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Позволяет изменять алгоритм независимо от клиента, который его использует.
    protocol SortingStrategy {
        func sort<T: Comparable>(_ array: [T]) -> [T]
    }
    class BubbleSortStrategy: SortingStrategy { /* ... */ }
    class QuickSortStrategy: SortingStrategy { /* ... */ }
    class DataProcessor {
        private var sorter: SortingStrategy
        init(sorter: SortingStrategy) { self.sorter = sorter }
        func process(data: [Int]) -> [Int] { return sorter.sort(data) }
    }

В iOS-разработке также широко применяются архитектурные паттерны (MVC, MVVM, VIPER), которые организуют код на уровне всего модуля или приложения.