golang实现设计模式之观察者模式-优缺点,适用场景

发布时间 2023-06-09 18:22:40作者: 进击的davis

观察者模式是一种行为型模式,其定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。

观察者模式常用 订阅/发布机制,即发布者持有所有订阅者,当发布者状态变更或者特定行为时,通知所有订阅者。

结构

  • 1.发布者。属性及行为:属性,订阅者列表,行为,添加、删除订阅者方法,在自身状态改变或特定行为发生时通知订阅者。
  • 2.抽象订阅者,声明update更新方法。
  • 3.具体订阅者,通知时执行方法。
  • 4.客户端,分别创建发布者订阅者对象,并且为发布者添加订阅者对象。

优缺点

  • 优点

1.开闭原则。无需修改发布者代码就能引入新的订阅者类。
2.可以在运行时建立对象之间的联系。

  • 缺点

1.订阅者的通知顺序是随机的。
个人理解,如果订阅者是列表,执行通知 Notify() 是遍历列表的话,应该有顺序

适用场景

  • 1.当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化的时。
  • 2.当应用中的一些对象必须观察其他对象时, 可使用该模式。

代码实现

package main

import "fmt"

// 1.publisher
type iPublish interface {
   register(s iSub)
   remove(s iSub)
   notify()
}

type pub struct {
   name string
   inStock bool
   subs []iSub
}

func NewPub(name string) *pub {
   return &pub{name: name}
}

func (r *pub) register(s iSub)  {
   r.subs = append(r.subs, s)
}

func (r *pub) remove(s iSub)  {
   if len(r.subs) == 0 {
      return
   }

   for i := 0; i < len(r.subs); i++ {
      if r.subs[i] == s {
         r.subs = append(r.subs[:i], r.subs[i+1:]...)
      }
   }
}

func (r *pub) notify()  {
   if len(r.subs) == 0 {
      return
   }
   for i := 0; i < len(r.subs); i++ {
      r.subs[i].update()
   }
}

// 2.abstract subscribe
type iSub interface {
   update()
}

// 3.concrete subscribe
type subSports struct {
   name string
}

func (r *subSports) update()  {
   fmt.Printf("sub-sports %s received notify.\n", r.name)
}

type subFood struct {
   name string
}

func (r *subFood) update()  {
   fmt.Printf("sub-food %s received notify.\n", r.name)
}

type subDigits struct {
   name string
}

func (r *subDigits) update()  {
   fmt.Printf("sub-digits %s received notify.\n", r.name)
}

// 4.client
func main()  {
   p := NewPub("shopping")
   p.register(&subSports{"Anta"})
   p.register(&subFood{"Pepsi"})
   p.register(&subSports{"Apple"})
   p.notify()
}

参考文章: