Patrón de Diseño Observer en Go: Implementación Práctica
Clase 12 de 19 • Curso de Go Avanzado: Concurrencia y Patrones de Diseño
Resumen
¿Qué es el patrón de diseño Observer?
El Observer es un patrón de diseño de comportamiento que se utiliza para permitir que un objeto informe a otros objetos sobre cambios en su estado. Este patrón resulta muy útil para situaciones donde se necesita notificar a múltiples objetos cuando ocurre un evento específico, todo sin causar problemas de rendimiento.
¿Por qué es útil este patrón?
La aplicación de Observer es particularmente beneficiosa al evitar que los objetos tengan que preguntar repetidamente por el estado de un evento. En lugar de ello, el objeto que sufre el cambio notifica directamente a los observadores interesados, mejorando así la eficiencia.
¿Cómo implementar el patrón Observer en Go?
Para demostrar la implementación de Observer en Go, crearemos un sistema de notificación similar al de una tienda en línea, notificando a los clientes cuando un producto vuelva a estar disponible.
Definición del tópico y el observador
Vamos a comenzar definiendo una interfaz Topic
y un tipo Observer
. Aquí está el esqueleto básico:
package main
type Observer interface {
GetID() string
UpdateValue(value string)
}
type Topic interface {
Register(observer Observer)
Broadcast()
}
type Item struct {
observers []Observer
name string
available bool
}
Creación de un nuevo ítem
Creamos un constructor para nuestros ítems, representando un producto en la tienda.
func NewItem(name string) *Item {
return &Item{
name: name,
available: false,
}
}
func (i *Item) UpdateAvailable() {
fmt.Printf("El ítem %s está disponible\n", i.name)
i.available = true
i.Broadcast()
}
Implementación de métodos del ítem
Ahora, implementamos los métodos Register
y Broadcast
para gestionar los observadores.
func (i *Item) Register(observer Observer) {
i.observers = append(i.observers, observer)
}
func (i *Item) Broadcast() {
for _, observer := range i.observers {
observer.UpdateValue(i.name)
}
}
Definición de un observador
Creamos una estructura que represente a los observadores, en este caso, un sistema de notificación por email.
type EmailClient struct {
id string
}
func (e *EmailClient) GetID() string {
return e.id
}
func (e *EmailClient) UpdateValue(value string) {
fmt.Printf("Enviando email: El ítem %s está disponible; Notificado al cliente %s\n", value, e.id)
}
Configuración del main
Finalmente, en la función main
, creamos un ítem, agregamos observadores y actualizamos la disponibilidad del ítem.
func main() {
nvidiaItem := NewItem("RTX 3080")
firstObserver := &EmailClient{id: "1234"}
secondObserver := &EmailClient{id: "5678"}
nvidiaItem.Register(firstObserver)
nvidiaItem.Register(secondObserver)
nvidiaItem.UpdateAvailable()
}
Ejecutar este código enviará notificaciones a todos los observadores registrados cuando el ítem se vuelva disponible.
Ventajas de usar Observer
- Reducción de consultas constantes: No es necesario que los observadores pregunten constantemente si un evento ha ocurrido.
- Organización de código: El código se estructura de manera más clara y fácil de mantener, ya que separa claramente los objetos notificados de los observadores.
- Escalabilidad: Permite agregar nuevos observadores sin modificar el objeto observado.
El patrón Observer es una poderosa herramienta para manejar suscripciones y notificaciones en cualquier programa. Su uso puede mejorar significativamente el rendimiento y la estructura de tus aplicaciones. ¡Anímate a implementarlo y observa los beneficios!