Observer
Muammo: biror hodisa yuz berganda bir necha manfaatdor tomon xabardor bo’lishi kerak, lekin hodisa manbai kim tinglayotganini oldindan bilmasligi lozim. Obunachilar erkin qo’shilib-chiqib turadi.
G’oya: manba (broker) obunachilar ro’yxatini saqlaydi va hodisa bo’lganda hammasiga xabar tarqatadi (pub/sub). Go da bu tabiiy ravishda channellar orqali quriladi - har bir obunachiga alohida channel.
package main
import (
"fmt"
"sync"
)
// Broker - oddiy pub/sub. Har bir obunachi o'z channeliga ega.
type Broker struct {
mu sync.Mutex
subs []chan string
}
func (b *Broker) Subscribe() <-chan string {
b.mu.Lock()
defer b.mu.Unlock()
ch := make(chan string, 8) // buffer: Publish bloklanmasin
b.subs = append(b.subs, ch)
return ch
}
func (b *Broker) Publish(msg string) {
b.mu.Lock()
defer b.mu.Unlock()
for _, ch := range b.subs {
ch <- msg
}
}
func (b *Broker) Close() {
b.mu.Lock()
defer b.mu.Unlock()
for _, ch := range b.subs {
close(ch)
}
}
func main() {
broker := &Broker{}
sub1 := broker.Subscribe()
sub2 := broker.Subscribe()
broker.Publish("event: A")
broker.Publish("event: B")
broker.Close()
for msg := range sub1 {
fmt.Println("obunachi-1:", msg)
}
for msg := range sub2 {
fmt.Println("obunachi-2:", msg)
}
}$ go run observer.go
obunachi-1: event: A
obunachi-1: event: B
obunachi-2: event: A
obunachi-2: event: BHar ikkala obunachi bir xil hodisalarni oldi; Publish esa ular kimligini bilmadi.
Qachon: hodisaga asoslangan tizimlar, bildirishnomalar, real vaqtli yangilanishlar uchun. Go note: channel Observer’ni deyarli bepul beradi; real ilovada obunani bekor qilish va sekin obunachilar (buffer to’lishi) haqida o’ylash kerak.
Manba / batafsil: refactoring.guru/design-patterns/observer