Golang – 常用设计Observer Pattern
在Go中,可以使用channel和goroutine来实现监听设计
- 定义好Observer的Interface
// Observer 定义观察者接口
type Observer interface {
Update(string)
}
2. 定义好 Subject 对象
// Subject 定义主题对象
type Subject struct {
observers []Observer // 观察者列表
mutex sync.Mutex // 互斥锁,用于保护观察者列表
}
// RegisterObserver 注册观察者
func (s *Subject) RegisterObserver(o Observer) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.observers = append(s.observers, o)
}
// DeregisterObserver 注销观察者
func (s *Subject) DeregisterObserver(o Observer) {
s.mutex.Lock()
defer s.mutex.Unlock()
for i, observer := range s.observers {
if observer == o {
s.observers = append(s.observers[:i], s.observers[i+1:]...)
//s.observers[:i] 举例:0,1,2,3,4 , 使用:x[:2] , 输出: 0,1
//获取切片顺序N-1之前的
//s.observers[i+1:] 举例:0,1,2,3,4 , 使用:x[3:] , 输出: 3,4
//获取切片N++之后的
//... 把最后切片分别展开作为输入的参数
break
}
}
}
// NotifyObservers 通知观察者
func (s *Subject) NotifyObservers(msg string) {
for _, observer := range s.observers {
observer.Update(msg)
}
}
3. 定义好 RealObserver
// RealObserver 具体观察者实现
type RealObserver struct {
id int
}
// Update 更新方法
func (co *RealObserver) Update(msg string) {
fmt.Printf("观察者 %d 收到消息: %s\n", co.id, msg)
}
4. 使用案例
func main() {
// 声明需要的主题和真实观察者
subject := &Subject{}
observer1 := &RealObserver{id: 1}
observer2 := &RealObserver{id: 2}
// 注册观察者
subject.RegisterObserver(observer1)
subject.RegisterObserver(observer2)
// 异步发送通知
go func() {
for i := 0; i < 5; i++ {
subject.NotifyObservers(fmt.Sprintf("消息 %d", i+1))
time.Sleep(time.Second)
}
}()
// 模拟3秒后注销观察者
time.Sleep(3 * time.Second)
subject.DeregisterObserver(observer2)
time.Sleep(3 * time.Second)
}
显示结果:
观察者 1 收到消息: 消息 1
观察者 2 收到消息: 消息 1
观察者 1 收到消息: 消息 2
观察者 2 收到消息: 消息 2
观察者 1 收到消息: 消息 3
观察者 2 收到消息: 消息 3
观察者 1 收到消息: 消息 4
观察者 1 收到消息: 消息 5
Facebook评论