3、观察者模式

观察者模式(Observer)定义了对象之间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。在Go中,可以使用接口和切片实现观察者模式:

定义

package observer

import "fmt"

// 观察者接口
type Observer interface {
    Update(subject *Subject)
}

// 主题结构体
type Subject struct {
    observers []Observer
    state     int
}

// 注册观察者
func (s *Subject) Attach(observer Observer) {
    s.observers = append(s.observers, observer)
}

// 移除观察者
func (s *Subject) Detach(observer Observer) {
    for i, obs := range s.observers {
        if obs == observer {
            s.observers = append(s.observers[:i], s.observers[i+1:]...)
            break
        }
    }
}

// 通知所有观察者
func (s *Subject) Notify() {
    for _, observer := range s.observers {
        observer.Update(s)
    }
}

// 改变状态
func (s *Subject) SetState(state int) {
    s.state = state
    fmt.Printf("主题状态改变为: %d\n", state)
    s.Notify()
}

// 获取状态
func (s *Subject) GetState() int {
    return s.state
}

// 具体观察者A
type ConcreteObserverA struct {
    ID string
}

func (o ConcreteObserverA) Update(subject *Subject) {
    fmt.Printf("观察者A(%s)收到更新: 状态 = %d\n", o.ID, subject.GetState())
}

// 具体观察者B
type ConcreteObserverB struct {
    ID string
}

func (o ConcreteObserverB) Update(subject *Subject) {
    fmt.Printf("观察者B(%s)收到更新: 状态 = %d\n", o.ID, subject.GetState())
}

使用

// main.go
package main

import (
    "myapp/observer"
)

func main() {
    // 创建主题
    subject := &observer.Subject{}
    
    // 创建观察者
    observerA1 := observer.ConcreteObserverA{ID: "A1"}
    observerA2 := observer.ConcreteObserverA{ID: "A2"}
    observerB1 := observer.ConcreteObserverB{ID: "B1"}
    
    // 注册观察者
    subject.Attach(observerA1)
    subject.Attach(observerA2)
    subject.Attach(observerB1)
    
    // 改变状态,触发通知
    subject.SetState(1)
    
    // 取消注册一个观察者
    subject.Detach(observerA1)
    
    // 再次改变状态
    subject.SetState(2)
}