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

Какие знаешь паттерны которые используются по дефолту в Swift?

1.6 Junior🔥 171 комментариев
#Язык Swift

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

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

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

Паттерны проектирования в Swift по умолчанию

Swift как язык и его стандартная библиотека активно используют несколько ключевых паттернов проектирования, которые стали идиоматическими для iOS/macOS разработки. Эти паттерны глубоко интегрированы в экосистему и часто применяются "из коробки".

1. Шаблонный метод (Template Method)

Протоколы с extension-реализациями по умолчанию — это классический пример шаблонного метода. Разработчик может реализовать только необходимые методы, а остальные получают стандартное поведение:

protocol DataProcessor {
    func fetchData() -> Data
    func processData(_ data: Data) -> ProcessedData
    func saveResult(_ result: ProcessedData)
}

extension DataProcessor {
    // Реализация по умолчанию
    func processData(_ data: Data) -> ProcessedData {
        // Базовая обработка
        return ProcessedData(data)
    }
    
    func saveResult(_ result: ProcessedData) {
        UserDefaults.standard.set(result.rawValue, forKey: "processed")
    }
}

// Класс использует только нужные части шаблона
class NetworkProcessor: DataProcessor {
    func fetchData() -> Data {
        // Специфичная реализация
        return Data()
    }
}

2. Делегирование (Delegate Pattern)

Это фундаментальный паттерн Cocoa/CocoaTouch, реализованный через протоколы и слабые ссылки:

protocol UITableViewDelegate: AnyObject {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
}

class ViewController: UIViewController, UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // Обработка выбора ячейки
    }
}

// Использование
let tableView = UITableView()
let delegate = ViewController()
tableView.delegate = delegate // weak reference автоматически

3. Строитель (Builder Pattern) через Result Builders

Swift 5.4 представил result builders, которые реализуют вариацию строителя для DSL-подобного синтаксиса:

@resultBuilder
struct HTMLBuilder {
    static func buildBlock(_ components: String...) -> String {
        return components.joined(separator: "\n")
    }
    
    static func buildArray(_ components: [String]) -> String {
        return components.joined(separator: "\n")
    }
}

@HTMLBuilder
func makePage() -> String {
    "<html>"
    "<body>"
    "<h1>Hello World</h1>"
    "</body>"
    "</html>"
}

4. Одиночка (Singleton)

Реализован через static let свойства с приватными инициализаторами — это идиоматический способ в Swift:

class AppSettings {
    static let shared = AppSettings()
    private init() {}
    
    var theme: String = "dark"
    var language: String = "ru"
}

// Использование
AppSettings.shared.theme = "light"

5. Наблюдатель (Observer Pattern)

Встроенные механизмы через property observers и Combine framework:

class User {
    var name: String {
        didSet {
            print("Имя изменилось с \(oldValue) на \(name)")
        }
        willSet {
            print("Устанавливается новое имя: \(newValue)")
        }
    }
    
    init(name: String) {
        self.name = name
    }
}

6. Фабричный метод (Factory Method)

Используется через инициализаторы и статические методы:

enum DocumentType {
    case pdf, word, txt
}

class Document {
    static func create(type: DocumentType) -> Document {
        switch type {
        case .pdf:
            return PDFDocument()
        case .word:
            return WordDocument()
        case .txt:
            return TextDocument()
        }
    }
}

7. Адаптер (Adapter Pattern)

Протоколы в Swift часто выступают как адаптеры между различными компонентами:

protocol PaymentProcessor {
    func process(amount: Decimal) -> Bool
}

class PayPalAdapter: PaymentProcessor {
    private let paypalService: PayPalService
    
    init(paypalService: PayPalService) {
        self.paypalService = paypalService
    }
    
    func process(amount: Decimal) -> Bool {
        // Адаптация интерфейса PayPalService к PaymentProcessor
        return paypalService.sendPayment(amount: amount.doubleValue)
    }
}

8. Стратегия (Strategy Pattern)

Реализуется через замыкания и протоколы с реализациями по умолчанию:

struct DataSorter {
    var sortingStrategy: (([Int]) -> [Int]) = { $0.sorted() }
    
    func sort(_ data: [Int]) -> [Int] {
        return sortingStrategy(data)
    }
}

// Изменение стратегии на лету
var sorter = DataSorter()
sorter.sortingStrategy = { $0.sorted(by: >) } // Нисходящая сортировка

Почему эти паттерны "по умолчанию"?

Swift спроектирован с учётом этих паттернов по нескольким причинам:

  1. Безопасность — strict typing и optionals предотвращают распространённые ошибки
  2. Производительность — многие паттерны реализованы на уровне компилятора
  3. Выразительность — лаконичный синтаксис делает код читаемым
  4. Совместимость с Objective-C и Cocoa фреймворками

Важные нюансы реализации:

  • Слабые ссылки в делегировании предотвращают retain cycles
  • Value types (structs/enums) часто предпочтительнее классов для простых паттернов
  • Протокол-ориентированное программирование заменяет некоторые классические ООП-паттерны
  • Модификаторы доступа (private, fileprivate, internal, public, open) обеспечивают инкапсуляцию

Эти паттерны стали "стандартными" не только потому, что они удобны, но и потому, что Swift предоставляет языковые конструкции, которые делают их реализацию безопасной, эффективной и выразительной. Они образуют основу идиоматического Swift-кода и широко используются в Apple фреймворках.

Какие знаешь паттерны которые используются по дефолту в Swift? | PrepBro