SOLDES de printemps
Observateur

Observateur en Go

L’Observateur est un patron de conception comportemental qui permet à certains objets d’envoyer des notifications concernant leur état à d’autres objets.

Ce patron fournit la possibilité aux objets qui implémentent une interface de souscription, de s’inscrire et de se désinscrire de ces événements.

Exemple conceptuel

Dans une boutique en ligne, les articles sont parfois en rupture de stock. Certains clients peuvent être intéressés par un de ces articles. Il existe des solutions pour ce problème :

  1. Le client peut vérifier régulièrement la disponibilité de l’article.
  2. La boutique va bombarder les clients de messages pour leur indiquer les nouveaux articles disponibles ou en stock.
  3. Le client s’inscrit à un article qui l’intéresse et recevra une notification dès qu’il sera à nouveau disponible. Bien entendu, plusieurs clients peuvent s’inscrire auprès du même produit.

La troisième méthode est la plus viable : c’est ce que le patron de conception observateur vous propose de faire. Voici ses composants principaux :

  • Le sujet, l’instance qui publie un événement si quelque chose se produit.
  • L’observateur, qui s’inscrit auprès des événements d’un sujet et reçoit une notification quand cela se produit.

subject.go: Sujet

package main

type Subject interface {
	register(observer Observer)
	deregister(observer Observer)
	notifyAll()
}

item.go: Sujet concret

package main

import "fmt"

type Item struct {
	observerList []Observer
	name         string
	inStock      bool
}

func newItem(name string) *Item {
	return &Item{
		name: name,
	}
}
func (i *Item) updateAvailability() {
	fmt.Printf("Item %s is now in stock\n", i.name)
	i.inStock = true
	i.notifyAll()
}
func (i *Item) register(o Observer) {
	i.observerList = append(i.observerList, o)
}

func (i *Item) deregister(o Observer) {
	i.observerList = removeFromslice(i.observerList, o)
}

func (i *Item) notifyAll() {
	for _, observer := range i.observerList {
		observer.update(i.name)
	}
}

func removeFromslice(observerList []Observer, observerToRemove Observer) []Observer {
	observerListLength := len(observerList)
	for i, observer := range observerList {
		if observerToRemove.getID() == observer.getID() {
			observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
			return observerList[:observerListLength-1]
		}
	}
	return observerList
}

observer.go: Observateur

package main

type Observer interface {
	update(string)
	getID() string
}

customer.go: Observateur concret

package main

import "fmt"

type Customer struct {
	id string
}

func (c *Customer) update(itemName string) {
	fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}

func (c *Customer) getID() string {
	return c.id
}

main.go: Code client

package main

func main() {

	shirtItem := newItem("Nike Shirt")

	observerFirst := &Customer{id: "abc@gmail.com"}
	observerSecond := &Customer{id: "xyz@gmail.com"}

	shirtItem.register(observerFirst)
	shirtItem.register(observerSecond)

	shirtItem.updateAvailability()
}

output.txt: Résultat de l’exécution

Item Nike Shirt is now in stock
Sending email to customer abc@gmail.com for item Nike Shirt
Sending email to customer xyz@gmail.com for item Nike Shirt

Observateur dans les autres langues

Observateur en C# Observateur en C++ Observateur en Java Observateur en PHP Observateur en Python Observateur en Ruby Observateur en Rust Observateur en Swift Observateur en TypeScript