Observer — conceptos clave del patrón de suscripción a cambios

Autor: IT Sectr Publicado: 2026-02-17 Tiempo de lectura: 7 min

Observer — un patrón de comportamiento en el que un objeto (el publicador) notifica a múltiples suscriptores sobre cambios en su estado. En el desarrollo móvil, Observer es la base de las mecánicas reactivas: la UI se suscribe a los cambios de datos y se actualiza automáticamente. El patrón está implementado en NotificationCenter en iOS y LiveData/Flow en Android. Más detalles en Refactoring Guru: Observer.

Puntos clave

  • Observer — un patrón de suscripción: un publicador, múltiples suscriptores
  • NotificationCenter — implementación integrada de Observer en iOS/macOS
  • Flow y LiveData — implementaciones reactivas de Observer en Android
  • Push vs Pull — el publicador puede enviar datos o notificar sobre eventos
  • Fugas de memoria — los suscriptores deben cancelar la suscripción para evitar fugas

¿Qué es Observer? La esencia del patrón observador

Observer — un patrón de comportamiento GoF que define una dependencia de uno a muchos entre objetos. Cuando un objeto (Subject u Observable) cambia su estado, todos los objetos dependientes (Observers) son notificados y actualizados automáticamente. El patrón implementa un acoplamiento débil: el publicador no conoce las clases específicas de los suscriptores, solo que implementan la interfaz Observer.

Estructura de Observer incluye la interfaz Subject con los métodos attach(), detach(), notify() y la interfaz Observer con el método update(). ConcreteSubject almacena el estado y la lista de suscriptores. ConcreteObserver implementa update() y reacciona a los cambios. En el desarrollo móvil, la implementación clásica de GoF es rara — es reemplazada por mecanismos integrados: NotificationCenter, Combine, Flow, LiveData, que implementan la misma idea con APIs modernas.

Modelo Push vs Pull — en el modelo Push, el Subject envía datos a todos los suscriptores (NotificationCenter.post). En el modelo Pull, el Subject solo notifica y el suscriptor solicita los datos por sí mismo. Android LiveData usa Push (los datos se pasan en observe()), RxJava/Flow soportan ambos modelos. La elección depende de la tarea: Push es más simple para actualizaciones de UI, Pull es más eficiente para grandes volúmenes de datos que el suscriptor puede no querer recibir.

Observer en iOS: NotificationCenter, Combine y KVO

NotificationCenter — un mecanismo integrado de iOS/macOS para implementar Observer. El publicador envía una Notification a través de NotificationCenter.default.post(name:, object:, userInfo:). El suscriptor se registra mediante addObserver(forName:, queue:, using:). NotificationCenter admite notificaciones con nombre (Notification.Name) y puede pasar cualquier dato en userInfo. UIKeyboardWillShowNotification, UIApplicationDidEnterBackgroundNotification — ejemplos del sistema.

swift
extension Notification.Name {
    static let userDidLogin = Notification.Name("userDidLogin")
}

// Publicador
NotificationCenter.default.post(
    name: .userDidLogin,
    object: nil,
    userInfo: ["userId": "123"]
)

// Suscriptor
class ProfileViewModel {
    private var observers: [NSObjectProtocol] = []

    func startObserving() {
        let observer = NotificationCenter.default.addObserver(
            forName: .userDidLogin,
            object: nil,
            queue: .main
        ) { [weak self] notification in
            guard let userId = notification.userInfo?["userId"] as? String else { return }
            // El suscriptor reacciona al evento
            self?.loadProfile(userId: userId)
        }
        observers.append(observer)
    }

    func stopObserving() {
        observers.forEach { NotificationCenter.default.removeObserver($0) }
        observers.removeAll()
    }
}

Framework Combine — una alternativa reactiva moderna a NotificationCenter, introducida en iOS 13. Publisher (NotificationCenter, URLSession, Timer) — el publicador, Subscriber (sink, assign) — el suscriptor. Combine añade operadores (map, filter, combineLatest) para la transformación de flujos de datos. @Published — un property wrapper que notifica automáticamente a los suscriptores sobre cambios. En MVVM con SwiftUI, Combine reemplaza a NotificationCenter para enlazar ViewModel y View.

KVO (Key-Value Observing) — un mecanismo antiguo de ObjC/Swift para observar propiedades individuales de objetos. @objc dynamic var name: String — una propiedad observable. observe(.name) — suscripción. KVO solo funciona con clases compatibles con @objc y herencia de ObjC. Apple recomienda Combine y @Published en lugar de KVO en proyectos nuevos. KVO sigue siendo relevante para la compatibilidad con UIKit en proyectos híbridos.

Observer en Android: LiveData, StateFlow y SharedFlow

LiveData — un componente de Android Architecture Components para implementar Observer. Una clase observable que notifica a los suscriptores sobre cambios de datos. LiveData respeta el ciclo de vida: los suscriptores (LifecycleOwner) se cancelan automáticamente al destruirse. LiveData usa el modelo Push: los datos se pasan en observe(). LiveData es el bloque de construcción básico de MVVM en Android antes de Jetpack Compose.

kotlin
// ViewModel — publicador
class UserViewModel : ViewModel() {
    private val _user = MutableLiveData<User?>(null)
    val user: LiveData<User?> = _user

    fun loadUser(id: String) {
        viewModelScope.launch {
            val result = userRepository.getUser(id)
            _user.value = result
        }
    }
}

// Fragment — suscriptor
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        viewModel.user.observe(viewLifecycleOwner) { user ->
            // El suscriptor reacciona a los cambios
            userName.text = user?.name
            userEmail.text = user?.email
        }
    }
}

StateFlow y SharedFlow — tipos reactivos de Kotlin Coroutines que reemplazaron a LiveData en Jetpack Compose. StateFlow — un contenedor de estado observable con un valor actual fijo. SharedFlow — un flujo hot configurable sin estado, adecuado para eventos únicos (navegación, toasts). Ambos tipos están estrechamente integrados con Compose: collectAsState(), collectAsEffect(). StateFlow es obligatorio en proyectos Android modernos con Compose.

LiveData vs StateFlow — LiveData está vinculado al ciclo de vida de Android, StateFlow es independiente de la plataforma. StateFlow admite corrutinas, operadores (map, filter) y se puede probar sin dependencias de Android. LiveData es más simple para la compatibilidad con Java. Google recomienda StateFlow para proyectos nuevos en Kotlin + Compose, LiveData para mantener proyectos heredados o código Java.

Gestión de suscripciones y fugas de memoria

Fugas de memoria — el principal problema de Observer sin una gestión adecuada de suscripciones. Si un suscriptor (Activity, Fragment, UIViewController) se destruye pero no se cancela su suscripción, el publicador sigue manteniendo una referencia a él y el recolector de basura no puede liberar la memoria. En Android, LifecycleOwner (Activity/Fragment) debe llamar a removeObserver() o usar observe(viewLifecycleOwner). En iOS — removeObserver en deinit o disposeBag en Combine.

PlataformaMecanismo ObserverCancelación automáticaCancelación manual
iOSNotificationCenterNoremoveObserver() en deinit
iOSCombine (sink)Nostore(in: &bag) — DisposeBag
iOSKVONoremoveObserver() en deinit
AndroidLiveDataSí (LifecycleOwner)removeObserver() opcional
AndroidStateFlowMediante viewModelScopecancel() Job al cancelar
AndroidRxJavaNodispose() en CompositeDisposable

Referencia débil en suscriptores — al usar closures en bloques de suscripción, use [weak self] en Swift y referencie el ámbito del ciclo de vida en Kotlin. LiveData gestiona automáticamente las suscripciones a través de LifecycleOwner — la suscripción está activa solo cuando el Lifecycle está en estado STARTED o RESUMED. StateFlow en Compose usa collectAsState() con conocimiento del ciclo de vida. NotificationCenter en iOS requiere [weak self] explícito porque el closure hace una referencia fuerte a self.

Observer vs Publicador-Suscriptor: diferencias

Observer (GoF) y Publicador-Suscriptor (PubSub) — patrones similares pero diferentes. En Observer, el publicador notifica directamente a los suscriptores llamando a sus métodos. El publicador conoce a los suscriptores (almacena una lista). En PubSub, el publicador y el suscriptor no se conocen — entre ellos hay un mediador (Event Bus, Message Queue, NotificationCenter). El publicador envía un mensaje a un canal, el suscriptor escucha el canal. PubSub tiene un acoplamiento más débil.

Ejemplos de PubSub en desarrollo móvil — NotificationCenter en iOS puede considerarse PubSub: el publicador no conoce a los suscriptores, simplemente publica una notificación. EventBus u Otto en Android (obsoletos). SharedFlow con BroadcastChannel — PubSub en el mundo Kotlin. En sistemas distribuidos, PubSub se implementa mediante RabbitMQ, Kafka, Google PubSub. Para el desarrollo móvil, PubSub es útil en arquitecturas modulares donde los módulos no deben depender unos de otros.

Qué elegir — para actualizaciones de UI (ViewModel → View), use Observer (LiveData, StateFlow, @Published). Para eventos entre módulos (autenticación, cierre de sesión, cambio de tema) — PubSub (SharedFlow, NotificationCenter, EventBus). Observer es más simple y eficiente dentro de una misma pantalla, PubSub es más flexible para eventos globales pero más difícil de depurar debido a dependencias implícitas.

Preguntas frecuentes

¿En qué se diferencia StateFlow de LiveData?

StateFlow es un tipo independiente de la plataforma de Kotlin Coroutines, mientras que LiveData está vinculado al ciclo de vida de Android. StateFlow admite corrutinas y operadores, y se puede probar sin Android. LiveData gestiona automáticamente las suscripciones a través de LifecycleOwner. Google recomienda StateFlow para proyectos nuevos en Kotlin + Compose, y LiveData para compatibilidad con Java.

¿Cómo evitar fugas de memoria con NotificationCenter?

Use [weak self] en el closure del manejador y llame a removeObserver() en deinit. Almacene una referencia al observer (NSObjectProtocol) y elimínela cuando el objeto se destruya. En Combine, use AnyCancellable y store(in:) para la cancelación automática al liberar el DisposeBag.

¿Se puede usar Observer en SwiftUI sin Combine?

Sí, SwiftUI admite ObservableObject con @Published y @StateObject/@ObservedObject — esta es una implementación integrada de Observer. @Published notifica automáticamente a la View sobre los cambios. Combine no es necesario: ObservableObject usa el Publisher objectWillChange integrado en SwiftUI. Combine añade operadores para la transformación de flujos.

¿Cuándo usar SharedFlow en lugar de StateFlow?

SharedFlow — para eventos únicos (navegación, toasts, Snackbar) donde no se necesita un valor actual. StateFlow — para el estado de la UI (lista de datos, progreso de carga) donde se necesita una instantánea actual. SharedFlow no tiene propiedad value y no devuelve el último valor a nuevos suscriptores.

¿Cuál es la diferencia entre KVO y Combine en iOS?

KVO es un mecanismo heredado de ObjC, requiere @objc dynamic y solo funciona con clases heredadas de NSObject. Combine es un framework moderno de Swift, type-safe, con operadores e integración con SwiftUI. Combine reemplaza a KVO y NotificationCenter. Apple recomienda Combine para proyectos nuevos, KVO solo para soporte heredado.

Resumen

  • Observer — un patrón de comportamiento para notificar a suscriptores sobre cambios
  • iOS NotificationCenter — implementación PubSub con notificaciones con nombre
  • iOS Combine — un framework reactivo con Publisher y Subscriber
  • Android LiveData — Observer con conocimiento del ciclo de vida de Android Architecture Components
  • Android StateFlow — un contenedor de estado reactivo para Compose y corrutinas
  • Gestión de memoria — cancelación obligatoria de suscripción para evitar fugas
  • Observer vs PubSub — suscripción directa vs mediador para acoplamiento débil

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también