欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > Golang学习笔记_41——观察者模式

Golang学习笔记_41——观察者模式

2025/7/2 9:37:00 来源:https://blog.csdn.net/LuckyLay/article/details/145992873  浏览:    关键词:Golang学习笔记_41——观察者模式

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. 解耦设计:主题与观察者无直接依赖()
  2. 动态扩展:支持运行时增减观察者()
  3. 事件驱动:适用于异步处理场景()

缺点

  1. 通知顺序:多个观察者的执行顺序不可控()
  2. 循环触发:不当设计可能引发循环调用()
  3. 性能开销:大量观察者时通知效率降低()

三、适用场景

1. 股票价格监控系统

// 股票主题
type StockSubject struct {observers []Observerprice     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 []Observerstatus    string
}func (d *DeviceMonitor) SetStatus(status string) {d.status = statusd.Notify()
}// 运维系统观察者
type OpsSystem struct{}func (o *OpsSystem) Update(status string) {if status == "ERROR" {fmt.Println("触发告警:设备异常")}
}

3. 电商订单状态通知

type OrderSubject struct {observers []Observerstate     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_demoimport ("fmt""sync""time"
)// OrderEvent 事件结构体
type OrderEvent struct {OrderId     stringAmount      float64PaymentTime time.TimeUserID      string
}// Observer 观察者接口
type Observer interface {Handle(event OrderEvent) errorName() 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.WaitGroupfor _, 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 广播通知审批流程处理
发布订阅引入消息代理解耦更彻底()分布式系统消息传递

七、实现建议

  1. 线程安全:使用sync.Mutex保证并发安全()
  2. 批量通知:使用copy避免通知过程中列表变更(见示例)
  3. 性能优化:对于大量观察者采用批处理或异步通知()
  4. 防止泄漏:及时移除无效观察者()

八、典型应用

  1. GUI事件处理:如按钮点击事件监听()
  2. 微服务配置中心:配置变更通知服务集群()
  3. 游戏引擎:玩家状态变化触发多系统响应()

通过这种设计模式,可以构建出松耦合、易扩展的事件驱动系统。在实际Go开发中,结合channel特性还能实现更高效的观察者模式变体。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词