← Biblioteca técnica
Architecture · APUNTE DE ESTUDIO

Patrones de diseño iOS: Factory, Builder, Coordinator y Strategy

Qué problema resuelve cada patrón, ejemplos Swift y cuándo evita o añade complejidad.

Empieza por el problema, no por el nombre

Un patrón es una solución recurrente con compromisos. Factory construye objetos; Builder compone configuraciones; Coordinator gestiona navegación; Strategy sustituye un comportamiento; Singleton ofrece una instancia compartida. Usarlo sin necesidad añade complejidad.

Factory — construir y ensamblar

Factory sencilla
struct AccountsViewModel {
    let repository: any AccountsRepository
}
protocol AccountsRepository { }
struct LiveRepository: AccountsRepository { }
enum AccountsFactory {
    static func makeLiveViewModel() -> AccountsViewModel {
        AccountsViewModel(repository: LiveRepository())
    }
}

Trade-off: una factoría evita repetir construcción compleja, pero no necesita jerarquías de clases para cada objeto.

Builder — configuración progresiva

Builder de configuración
import Foundation
struct RequestConfiguration {
    let baseURL: URL
    let timeout: TimeInterval
    let cacheEnabled: Bool
}
struct RequestBuilder {
    let baseURL: URL
    var timeout: TimeInterval = 30
    var cacheEnabled = false
    func build() -> RequestConfiguration {
        RequestConfiguration(baseURL: baseURL, timeout: timeout,
                             cacheEnabled: cacheEnabled)
    }
}

Trade-off: evita el Builder cuando un inicializador con pocos argumentos expresa mejor el objeto.

Coordinator — navegación

Modelo de Coordinator con NavigationStack
import SwiftUI
@MainActor @Observable
final class AppCoordinator {
    var path: [Route] = []
    enum Route: Hashable { case account(String), settings }
    func showAccount(id: String) { path.append(.account(id)) }
    func goBack() { if !path.isEmpty { path.removeLast() } }
}
// Usa NavigationStack(path:) y navigationDestination(for:).

Trade-off: útil con deep links y flujos grandes; innecesario en pantallas simples.

Strategy — comportamiento intercambiable

Varias políticas sin switches crecientes
import Foundation
protocol FeeStrategy {
    func fee(for amount: Decimal) -> Decimal
}
struct FlatFee: FeeStrategy {
    func fee(for amount: Decimal) -> Decimal { 2 }
}
struct PercentageFee: FeeStrategy {
    func fee(for amount: Decimal) -> Decimal { amount * 0.02 }
}
struct Checkout {
    let fees: any FeeStrategy
    func total(_ amount: Decimal) -> Decimal {
        amount + fees.fee(for: amount)
    }
}

Singleton no sustituye DI

Una instancia global puede ser válida para infraestructura inmutable de proceso, pero si guarda estado mutable compartido esconde dependencias y puede acoplar pruebas.

Selección de patrones
PatrónPreguntaEvitar si
Factory¿Quién construye?Inicializador trivial
Builder¿Cómo componer opciones?Configuración pequeña
Coordinator¿Quién decide la navegación?Vista sencilla
Strategy¿Cómo intercambiar algoritmos?Solo hay una variante
Singleton¿Se necesita una instancia global?Oculta estado compartido
FUENTES Y DOCUMENTACIÓN

Notas personales de estudio. Verifica los matices según la versión de Swift/iOS y la documentación oficial.