Golang学习笔记_41——观察者模式
- 手机
- 2025-09-15 01:42:02

Golang学习笔记_38——享元模式 Golang学习笔记_39——策略模式 Golang学习笔记_40——模版方法模式
文章目录 一、核心概念1. 定义2. 解决的问题3. 核心角色4. 类图 二、特点分析三、适用场景1. 股票价格监控系统2. 物联网设备状态监控3. 电商订单状态通知 四、Go语言实现示例完整实现代码执行结果 五、高级应用1. 异步通知机制(参考网页10)2. 事件过滤机制 六、与其他模式对比七、实现建议八、典型应用
一、核心概念 1. 定义
观察者模式是一种行为型设计模式,建立对象间的一对多依赖关系,当一个对象(主题)状态改变时,自动通知所有依赖对象(观察者)。其核心特点包括:
松耦合设计:主题与观察者通过接口交互()动态订阅:运行时增减观察者()广播通知:状态变化自动触发多对象更新() 2. 解决的问题 状态同步:多个对象需实时获取核心对象状态变化事件驱动:构建解耦的事件响应系统()资源监控:如CPU使用率报警() 3. 核心角色 角色作用Subject维护观察者列表,定义注册/移除/通知方法()Observer定义更新接口,接收主题通知()ConcreteSubject实现具体状态管理和通知逻辑ConcreteObserver实现业务响应逻辑 4. 类图 @startuml interface Subject { + Register(Observer) + Remove(Observer) + Notify() } interface Observer { + Update() } class ConcreteSubject { - state: int + SetState(int) } class ConcreteObserver { + Update() } Subject <|-- ConcreteSubject Observer <|-- ConcreteObserver ConcreteSubject "1" *-- "0..*" Observer @enduml 二、特点分析优点
解耦设计:主题与观察者无直接依赖()动态扩展:支持运行时增减观察者()事件驱动:适用于异步处理场景()缺点
通知顺序:多个观察者的执行顺序不可控()循环触发:不当设计可能引发循环调用()性能开销:大量观察者时通知效率降低() 三、适用场景 1. 股票价格监控系统 // 股票主题 type StockSubject struct { observers []Observer price float64 } func (s *StockSubject) Register(o Observer) { s.observers = append(s.observers, o) } func (s *StockSubject) Notify() { for _, o := range s.observers { o.Update(s.price) } } // 手机APP观察者 type MobileApp struct{} func (m *MobileApp) Update(price float64) { fmt.Printf("手机端收到股价更新: %.2f\n", price) } 2. 物联网设备状态监控 // 设备状态主题 type DeviceMonitor struct { observers []Observer status string } func (d *DeviceMonitor) SetStatus(status string) { d.status = status d.Notify() } // 运维系统观察者 type OpsSystem struct{} func (o *OpsSystem) Update(status string) { if status == "ERROR" { fmt.Println("触发告警:设备异常") } } 3. 电商订单状态通知 type OrderSubject struct { observers []Observer state string } func (o *OrderSubject) Ship() { o.state = "SHIPPED" o.Notify() } // 短信通知观察者 type SMSNotifier struct{} func (s *SMSNotifier) Update(state string) { if state == "SHIPPED" { fmt.Println("发送物流短信通知") } } 四、Go语言实现示例 完整实现代码 package observer_demo import ( "fmt" "sync" "time" ) // OrderEvent 事件结构体 type OrderEvent struct { OrderId string Amount float64 PaymentTime time.Time UserID string } // Observer 观察者接口 type Observer interface { Handle(event OrderEvent) error Name() string } // OrderSubject 主题接口 type OrderSubject interface { Subscribe(observer Observer) UnSubscribe(observer Observer) Notify(event OrderEvent) } // OrderService 具体主题实现 type OrderService struct { Observer sync.Map // 使用现成安全的Map存储观察者 wg sync.WaitGroup } func (s *OrderService) Subscribe(observer Observer) { s.Observer.Store(observer.Name(), observer) } func (s *OrderService) UnSubscribe(observer Observer) { s.Observer.Delete(observer.Name()) } func (s *OrderService) Notify(event OrderEvent) { s.Observer.Range(func(key, value interface{}) bool { observer := value.(Observer) s.wg.Add(1) go func(obs Observer) { defer s.wg.Done() // 带超时控制的处理 done := make(chan struct{}) go func() { defer close(done) if err := retry(3, time.Second, func() error { return obs.Handle(event) }); err != nil { fmt.Printf("[Error] %s处理失败: %v\n", obs.Name(), err) } }() select { case <-done: fmt.Printf("[Info] %s处理完成\n", obs.Name()) case <-time.After(5 * time.Second): fmt.Printf("[Error] %s处理超时\n", obs.Name()) } }(observer) return true }) s.wg.Wait() } // 重试函数 func retry(attempts int, sleep time.Duration, fn func() error) error { if err := fn(); err != nil { if attempts--; attempts > 0 { time.Sleep(sleep) return retry(attempts, sleep, fn) } return err } return nil } // InventoryObserver 具体观察者实现 type InventoryObserver struct { } func (i *InventoryObserver) Name() string { return "InventoryObserver" } func (i *InventoryObserver) Handle(event OrderEvent) error { // 模拟库存扣减操作 fmt.Printf("库存系统:订单%s扣减库存,用户%s,金额%.2f\n", event.OrderId, event.UserID, event.Amount) return nil } // LogisticsObserver 具体观察者实现:物流业务 type LogisticsObserver struct { } func (l *LogisticsObserver) Name() string { return "LogisticsObserver" } func (l *LogisticsObserver) Handle(event OrderEvent) error { // 模拟物流操作 fmt.Printf("物流系统:订单%s发货,用户%s,金额%.2f\n", event.OrderId, event.UserID, event.Amount) return nil } // UserObserver 具体观察者实现,用户服务 type UserObserver struct { } func (u *UserObserver) Name() string { return "UserObserver" } func (u *UserObserver) Handle(event OrderEvent) error { // 模拟用户服务操作 fmt.Printf("用户服务:订单%s创建成功,用户%s,金额%.2f\n", event.OrderId, event.UserID, event.Amount) return nil } func test() { // 创建主题 orderService := &OrderService{} // 创建观察者 inventoryObserver := &InventoryObserver{} logisticsObserver := &LogisticsObserver{} userObserver := &UserObserver{} // 注册观察者 orderService.Subscribe(inventoryObserver) orderService.Subscribe(logisticsObserver) orderService.Subscribe(userObserver) // 模拟支付成功事件 event := OrderEvent{ OrderId: "20230303123456", Amount: 2999.00, PaymentTime: time.Now(), UserID: "1001", } // 通知观察者 fmt.Println("=== 开始通知观察者 ===") orderService.Notify(event) fmt.Println("=== 所有通知处理完成 ===") } 执行结果 === RUN Test_test === 开始通知观察者 === 物流系统:订单20230303123456发货,用户1001,金额2999.00 [Info] LogisticsObserver处理完成 用户服务:订单20230303123456创建成功,用户1001,金额2999.00 [Info] UserObserver处理完成 库存系统:订单20230303123456扣减库存,用户1001,金额2999.00 [Info] InventoryObserver处理完成 === 所有通知处理完成 === --- PASS: Test_test (0.00s) PASS 五、高级应用 1. 异步通知机制(参考网页10) func (w *WeatherStation) asyncNotify() { w.mu.Lock() observers := make([]Observer, len(w.observers)) copy(observers, w.observers) w.mu.Unlock() var wg sync.WaitGroup for _, o := range observers { wg.Add(1) go func(obs Observer) { defer wg.Done() obs.Update(w.temp) }(o) } wg.Wait() } 2. 事件过滤机制 type SmartObserver struct { lastTemp float64 } func (s *SmartObserver) Update(temp float64) { if math.Abs(temp-s.lastTemp) > 1.0 { fmt.Println("温度变化超过1度") s.lastTemp = temp } } 六、与其他模式对比 模式核心区别典型场景中介者模式通过中介协调多对象交互复杂对象间通信责任链模式请求沿链传递 vs 广播通知审批流程处理发布订阅引入消息代理解耦更彻底()分布式系统消息传递 七、实现建议 线程安全:使用sync.Mutex保证并发安全()批量通知:使用copy避免通知过程中列表变更(见示例)性能优化:对于大量观察者采用批处理或异步通知()防止泄漏:及时移除无效观察者() 八、典型应用 GUI事件处理:如按钮点击事件监听()微服务配置中心:配置变更通知服务集群()游戏引擎:玩家状态变化触发多系统响应()通过这种设计模式,可以构建出松耦合、易扩展的事件驱动系统。在实际Go开发中,结合channel特性还能实现更高效的观察者模式变体。
Golang学习笔记_41——观察者模式由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Golang学习笔记_41——观察者模式”
上一篇
层次聚类R复现