19 Stimmen

Beobachtermuster in der Sprache Go

Dieses Problem ist ziemlich häufig: ein Objekt sollte alle seine Abonnenten benachrichtigen, wenn ein Ereignis eintritt. In C++ können wir verwenden boost::signals oder etwas anderes. Aber wie macht man das in der Sprache Go? Es wäre schön, einige funktionierende Code-Beispiel, wo ein paar Objekte zu einem Verleger abonniert sind und verarbeiten Benachrichtigungen zu sehen.

Gracias

23voto

cthom06 Punkte 8999

Das ist in Go eigentlich ziemlich einfach. Verwenden Sie Kanäle. Für solche Dinge sind sie gemacht.

type Publish struct {
    listeners []chan *Msg
}

type Subscriber struct {
    Channel chan *Msg
}

func (p *Publisher) Sub(c chan *Msg) {
    p.appendListener(c)
}

func (p *Publisher) Pub(m *Msg) {
    for _, c := range p.listeners {
        c <- Msg
    }
}

func (s *Subscriber) ListenOnChannel() {
    for {
        data := <-s.Channel
        //Process data
    }
}

func main() {
    for _, v := range subscribers {
        p.Sub(v.Channel)
        go v.ListenOnChannel()
    }
    //Some kind of wait here
}

Natürlich ist dies kein funktionierendes Codebeispiel. Aber es ist nah dran.

2voto

Jerry An Punkte 507

Hier gebe ich eine klassische Implementierung ohne Kanäle an, die Sie gerne verwenden können Beitrag enter image description here

Angenommenes Beispiel: Angenommen, Sie interessieren sich für den Aktienmarkt. Sie haben die folgenden Bedürfnisse: Sie möchten die Aktienkurse eines bestimmten Unternehmens (z. B. Apple Inc.) im Auge behalten. Sie möchten keine Kursaktualisierung verpassen, insbesondere dann nicht, wenn der Kurs bis zu einem bestimmten Punkt sinkt. Sie möchten über alle Aktienkursaktualisierungen benachrichtigt werden.

Schnittstellen:

// Subject interface
type Subject interface {
    Attach(o Observer) (bool, error)
    Detach(o Observer) (bool, error)
    Notify() (bool, error)
}

// Observer Interface
type Observer interface {
    Update(string)
}

Konkretes Beobachterobjekt

// Concrete Observer: StockObserver
type StockObserver struct {
    name string
}

func (s *StockObserver) Update(t string) {
    // do something
    println("StockObserver:", s.name, "has been updated,", "received subject string:", t)
}

Konkretes Subjekt-Objekt

// Concrete Subject: stockMonitor
type StockMonitor struct {
    // internal state
    ticker string
    price  float64

    observers []Observer
}

func (s *StockMonitor) Attach(o Observer) (bool, error) {

    for _, observer := range s.observers {
        if observer == o {
            return false, errors.New("Observer already exists")
        }
    }
    s.observers = append(s.observers, o)
    return true, nil
}

func (s *StockMonitor) Detach(o Observer) (bool, error) {

    for i, observer := range s.observers {
        if observer == o {
            s.observers = append(s.observers[:i], s.observers[i+1:]...)
            return true, nil
        }
    }
    return false, errors.New("Observer not found")
}

func (s *StockMonitor) Notify() (bool, error) {
    for _, observer := range s.observers {
        observer.Update(s.String())
    }
    return true, nil
}

func (s *StockMonitor) SetPrice(price float64) {
    s.price = price
    s.Notify()
}

func (s *StockMonitor) String() string {
    convertFloatToString := strconv.FormatFloat(s.price, 'f', 2, 64)
    return "StockMonitor: " + s.ticker + " $" + convertFloatToString
}

main.go

func main() {

    // Create a new stockMonitor object
    stockMonitor := &StockMonitor{
        ticker: "AAPL",
        price:  0.0,
    }

    observerA := &StockObserver{
        name: "Observer A",
    }
    observerB := &StockObserver{
        name: "Observer B",
    }

    // Attach our Observers to the stockMonitor
    stockMonitor.Attach(observerA)
    stockMonitor.Attach(observerB)

    // Start the stockMonitor
    stockMonitor.Notify()

    // Change the price of the stockMonitor
    stockMonitor.SetPrice(500)

    // Detach an Observer from the stockMonitor
    stockMonitor.Detach(observerA)

    // Change the price of the stockMonitor
    stockMonitor.SetPrice(528)
}

In diesem Teil

  • Wir erstellen zwei Beobachter, observerA und observerB. Verbinden Sie sie mit dem stockMonitor.
  • Ändern Sie den Preis der AktieMonitor.
  • Wir sehen, dass sowohl BeobachterA als auch BeobachterB benachrichtigt werden.
  • Trennen Sie observerA vom stockMonitor und ändern Sie den Aktienkurs. Wir können sehen, dass nur BeobachterB benachrichtigt wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X