1. Cos'è il pattern Observer
Il pattern Observer è un pattern di progettazione comportamentale utilizzato per stabilire una dipendenza uno-a-molti tra gli oggetti. In particolare, quando un oggetto (chiamato soggetto o osservabile) cambia, tutti i suoi dipendenti (chiamati osservatori) vengono notificati e aggiornati automaticamente. Questo pattern consente un accoppiamento debole tra soggetti e osservatori, conseguendo così un disaccoppiamento e una flessibilità tra gli oggetti.
2. Caratteristiche e vantaggi del pattern Observer
Il pattern Observer ha le seguenti caratteristiche e vantaggi:
- Accoppiamento debole tra soggetti e osservatori, dove il soggetto non ha bisogno di conoscere i dettagli specifici dell'implementazione degli osservatori.
- Aggiunta e rimozione dinamica degli osservatori, rendendo il sistema più flessibile.
- Segue il principio aperto-chiuso tra soggetti e osservatori, consentendo l'estensione e la riutilizzabilità indipendenti.
- Può stabilire una relazione di dipendenza uno-a-molti, in cui un soggetto può avere più osservatori.
3. Esempi di Applicazioni Pratiche del Pattern Observer
Il pattern Observer ha molte applicazioni pratiche nella vita reale, come:
- Meccanismo di gestione degli eventi nelle interfacce GUI, come la gestione delle azioni quando si fa clic su un pulsante.
- Push delle quotazioni in tempo reale del mercato azionario.
- Notifica delle attività promozionali su piattaforme di e-commerce.
4. Implementazione del Pattern Observer in Golang
4.1 Diagramma delle classi UML
4.2 Introduzione dell'Esempio
In questo esempio, abbiamo un soggetto (Subject) e due osservatori (ObserverA e ObserverB). Il soggetto può registrare, annullare la registrazione e notificare gli osservatori.
4.3 Passi di Implementazione
4.3.1 Creare l'Interfaccia del Soggetto e la Classe Concreta del Soggetto
type Subject interface {
RegisterObserver(observer Observer)
RemoveObserver(observer Observer)
NotifyObservers()
}
type ConcreteSubject struct {
observers []Observer
}
// Registrare l'oggetto ascoltatore
func (subject *ConcreteSubject) RegisterObserver(observer Observer) {
subject.observers = append(subject.observers, observer)
}
// Rimuovere l'oggetto ascoltatore
func (subject *ConcreteSubject) RemoveObserver(observer Observer) {
for i, obs := range subject.observers {
if obs == observer {
subject.observers = append(subject.observers[:i], subject.observers[i+1:]...)
break
}
}
}
// Notificare gli eventi
func (subject *ConcreteSubject) NotifyObservers() {
for _, observer := range subject.observers {
observer.Update()
}
}
4.3.2 Creare l'Interfaccia dell'Osservatore e le Classi Concreto dell'Osservatore
type Observer interface {
Update()
}
type ConcreteObserverA struct {}
func (observer *ConcreteObserverA) Update() {
fmt.Println("L'osservatore A è stato notificato.")
}
type ConcreteObserverB struct {}
func (observer *ConcreteObserverB) Update() {
fmt.Println("L'osservatore B è stato notificato.")
}
4.4 Esempio di Codice Demo
func main() {
subject := &ConcreteSubject{}
observerA := &ConcreteObserverA{}
observerB := &ConcreteObserverB{}
subject.RegisterObserver(observerA)
subject.RegisterObserver(observerB)
subject.NotifyObservers()
subject.RemoveObserver(observerA)
subject.NotifyObservers()
}
Output:
L'osservatore A è stato notificato.
L'osservatore B è stato notificato.
L'osservatore B è stato notificato.
Il codice di esempio sopra dimostra l'implementazione specifica del pattern observer. Il soggetto (ConcreteSubject) ha registrato due osservatori (ObserverA e ObserverB) e poi ha notificato questi due osservatori. Dopo di che, l'osservatore A è stato disiscritto dal soggetto e l'osservatore rimasto B è stato notificato nuovamente.