Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Observer

12/19
Recursos

Aportes 8

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

package main

import "fmt"

// Objects can suscribed to an event

type Topic interface {
	register(observer Observer) // Añadir observadores al objeto
	broadcast()                 // Notificar a todos los observadores
}

type Observer interface {
	getId() string      // Get the id of the observer
	updateValue(string) // Update the value of the observer, trigger the event
}

// Item -> No disponible
// Cuando tenga disponiblidad, avise a los observadores
type Item struct {
	observers []Observer // Lista de observadores
	name      string     // Nombre del item
	available bool       // Disponibilidad
}

// NewItem -> Crear un nuevo item
func NewItem(name string) *Item {
	return &Item{
		observers: make([]Observer, 0),
		name:      name,
		available: false,
	}
}

// Mandar el evento
func (i *Item) UpdateAvailable() {
	fmt.Println("Item", i.name, "is available")
	i.available = true
	i.broadcast()
}

// Mandar el evento a todos los observadores
func (i *Item) broadcast() {
	for _, o := range i.observers {
		o.updateValue(i.name)
	}
}

// Registrar un observador
func (i *Item) register(observer Observer) {
	i.observers = append(i.observers, observer)
}

type EmailClient struct {
	id string
}

func (e *EmailClient) getId() string {
	return e.id
}

func (e *EmailClient) updateValue(name string) {
	fmt.Println("Email to", e.id, "with item", name)
}

func main() {
	item := NewItem("TV")
	email1 := &EmailClient{id: "23ab"}
	item.register(email1)

	email2 := &EmailClient{id: "34dc"}
	item.register(email2)

	item.UpdateAvailable()
}

El código de la clase no está utilizando la interfaz Topic. Se puede comentar la interfaz y al correr el proceso, funciona igual.

https://www.youtube.com/watch?v=HFkZb1g8faA

en este video hay una explicacion con un ejemplo un poco mas claro 😃

Creo que la interfaz de Item estaba de mas, basándome en como funcionas los servicios Pub/Sub lo reduje simplemente a Topic/Observer . Tambien agregue otro tipo de Observer.

package main

import "fmt"

type Topic struct {
	observers []Observer
	name      string
	available bool
}

func NewTopic(name string) *Topic {
	return &Topic{
		name: name,
	}
}

func (i *Topic) UpdateAvailable() {
	fmt.Printf("Item %s is available\n", i.name)
	i.available = true
	i.broadcast()
}

func (i *Topic) broadcast() {
	for _, observer := range i.observers {
		observer.updateValue(i.name)
	}
}

func (i *Topic) register(observer Observer) {
	i.observers = append(i.observers, observer)
}

type Observer interface {
	getId() string
	updateValue(value string)
}

type EmailClient struct {
	id string
}

func (eC *EmailClient) getId() string {
	return eC.id
}

func (eC *EmailClient) updateValue(value string) {
	fmt.Printf("Sending email - %s available from client %s\n", value, eC.id)
}

type SMSClient struct {
	id string
}

func (sC *SMSClient) getId() string {
	return sC.id
}

func (sC *SMSClient) updateValue(value string) {
	fmt.Printf("Sending SMS - %s available from client %s\n", value, sC.id)
}

func main() {
	nvidiaTopic := NewTopic("RTX 3080")
	firstObserver := &EmailClient{
		id: "12ab",
	}
	secondObserver := &SMSClient{
		id: "34dc",
	}
	nvidiaTopic.register(firstObserver)
	nvidiaTopic.register(secondObserver)
	nvidiaTopic.UpdateAvailable()
}

Observer
Es un patrón de diseño de comportamiento, permite que un conjunto de objetos se suscriban a otro objeto para tener notificaciones acerca de la ocurrencia de un evento.

Refactoricé un poco la solución que da el profesor Néstor. En este enlace está todo el código que hice.

  • Cree una interface Topic y Observer con genéricos (go > 1.18)
  • Implementé un SyncTopic, el cual funciona como el de la clase. Los Observer se notifican de forma sincrónica.
  • Agregué una implementación de AsyncTopic, el cual abre una goroutina que es notificada con nuevos valores mediante un canal. Esto permite desacoplar el broadcast del hilo de ejecución principal.

Como feedback en general de las clases de patrones de diseño: sería valioso agregar un resumen de lo que se va a implementar con algún diagrama. No hace falta que sea UML riguroso, solo hace falta que muestre el problema/solución de forma resumida antes de ir a escribir el código.