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

Какие знаешь паттерны кроме архитектурных?

2.0 Middle🔥 133 комментариев
#Архитектура и паттерны#Язык Swift

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

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

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

Паттерны проектирования помимо архитектурных

Помимо архитектурных паттернов (MVC, MVP, MVVM, VIPER, Clean Architecture), в разработке под iOS активно применяются три основные категории шаблонов: порождающие, структурные и поведенческие паттерны. Эти классические паттерны из книги "Банды четырёх" (GoF) решают повседневные задачи проектирования классов и объектов.

Порождающие паттерны

Они абстрагируют процесс создания объектов, делая систему независимой от способа создания, композиции и представления объектов.

  1. Singleton (Одиночка) — гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему. В iOS часто используется для сервисов, менеджеров.

    class NetworkManager {
        static let shared = NetworkManager()
        private init() {}
    
        func fetchData() { /* ... */ }
    }
    // Использование
    NetworkManager.shared.fetchData()
    
  2. Factory Method (Фабричный метод) — определяет интерфейс для создания объекта, но позволяет подклассам изменять тип создаваемых объектов. Широко используется в UIKit (например, UICollectionViewCell регистрация и переиспользование).

    protocol Vehicle {
        func drive()
    }
    
    class Car: Vehicle { func drive() { print("Driving a car") } }
    class Bike: Vehicle { func drive() { print("Riding a bike") } }
    
    class VehicleFactory {
        static func createVehicle(type: String) -> Vehicle? {
            switch type {
            case "car": return Car()
            case "bike": return Bike()
            default: return nil
            }
        }
    }
    
  3. Builder (Строитель) — отделяет конструирование сложного объекта от его представления. Полезен для создания конфигурируемых объектов, например, URLRequest или UIAlertController.

    class Burger {
        let size: Int
        let cheese: Bool
        let bacon: Bool
        // ... другие свойства
    
        init(builder: BurgerBuilder) {
            self.size = builder.size
            self.cheese = builder.cheese
            self.bacon = builder.bacon
        }
    }
    
    class BurgerBuilder {
        var size = 10
        var cheese = false
        var bacon = false
    
        func addCheese() -> Self { self.cheese = true; return self }
        func addBacon() -> Self { self.bacon = true; return self }
    
        func build() -> Burger {
            return Burger(builder: self)
        }
    }
    
    // Использование
    let burger = BurgerBuilder().addCheese().addBacon().build()
    

Структурные паттерны

Они отвечают за построение удобных в поддержке иерархий классов.

  1. Adapter (Адаптер) — преобразует интерфейс одного класса в интерфейс, ожидаемый клиентом. Позволяет работать вместе классам с несовместимыми интерфейсами. Часто используется для интеграции сторонних библиотек или устаревшего кода.

    // Старая система
    class OldLogger {
        func logMessage(_ message: String) { print("Old: \(message)") }
    }
    
    // Новый требуемый интерфейс
    protocol NewLogger {
        func log(_ message: String)
    }
    
    // Адаптер
    class LoggerAdapter: NewLogger {
        private let oldLogger = OldLogger()
        func log(_ message: String) {
            oldLogger.logMessage(message.uppercased()) // Адаптация
        }
    }
    
  2. Decorator (Декоратор) — динамически добавляет объекту новые обязанности. В Swift реализуется через расширения (extensions) и композицию. Классический пример — модификация UIViewController с помощью child controllers.

    // Базовый компонент
    protocol Coffee {
        func cost() -> Double
    }
    
    class SimpleCoffee: Coffee {
        func cost() -> Double { return 2.0 }
    }
    
    // Декоратор
    class MilkDecorator: Coffee {
        private let decoratedCoffee: Coffee
        init(_ coffee: Coffee) { self.decoratedCoffee = coffee }
        func cost() -> Double { return decoratedCoffee.cost() + 0.5 }
    }
    
    let coffee: Coffee = SimpleCoffee()
    let coffeeWithMilk = MilkDecorator(coffee)
    print(coffeeWithMilk.cost()) // 2.5
    
  3. Facade (Фасад) — предоставляет унифицированный интерфейс к набору интерфейсов в подсистеме. Упрощает работу со сложными фреймворками, например, для работы с файловой системой или сетью.

Поведенческие паттерны

Они определяют алгоритмы и способы взаимодействия объектов.

  1. Observer (Наблюдатель) — определяет зависимость "один-ко-многим" между объектами так, что при изменении состояния одного объекта все зависящие от него оповещаются. В iOS это NotificationCenter и KVO (Key-Value Observing).

    class Subject {
        var state: Int = 0 {
            didSet { NotificationCenter.default.post(name: .stateChanged, object: state) }
        }
    }
    
    class Observer {
        init() {
            NotificationCenter.default.addObserver(self, selector: #selector(handleChange),
                                                   name: .stateChanged, object: nil)
        }
        @objc func handleChange(_ notification: Notification) {
            print("State changed to: \(notification.object ?? "")")
        }
    }
    
  2. Delegate (Делегат) — это фундаментальный паттерн Cocoa Touch. Он позволяет одному объекту поручить другому объекту выполнение специфических задач. Примеры: UITableViewDelegate, UIScrollViewDelegate.

  3. Strategy (Стратегия) — определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Позволяет изменять алгоритмы независимо от клиентов, которые ими пользуются. Часто применяется для реализации различных способов валидации, сортировки или сетевых стратегий.

    protocol PaymentStrategy {
        func pay(amount: Double)
    }
    
    class CreditCardPayment: PaymentStrategy {
        func pay(amount: Double) { print("Paid \(amount) via Credit Card") }
    }
    
    class PayPalPayment: PaymentStrategy {
        func pay(amount: Double) { print("Paid \(amount) via PayPal") }
    }
    
    class PaymentContext {
        private var strategy: PaymentStrategy
        init(strategy: PaymentStrategy) { self.strategy = strategy }
        func executePayment(amount: Double) { strategy.pay(amount: amount) }
    }
    

Эти паттерны, в отличие от архитектурных, решают более тактические задачи на уровне взаимодействия объектов. Их грамотное применение делает код более гибким, повторно используемым и тестируемым, что критически важно для поддержки и развития любого iOS-приложения. Современные подходы, такие как комбинирование паттернов (например, Factory + Dependency Injection) и использование возможностей Swift (протоколы, дженерики), позволяют применять эти шаблоны ещё эффективнее.