观察者模式

86 阅读2分钟

23 种经典的设计模式分为三类:创建型、结构型、行为型。创建型设计模式主要解决“对象的创建”问题,结构型设计模式主要解决“类或对象的组合或组装”问题,那行为型设计模式主要解决的就是“类或对象之间的交互”问题

观察者模式会对应不同的代码实现方式:有同步阻塞的实现方式,也有异步非阻塞的实现方式;有进程内的实现方式,也有跨进程的实现方式

观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern),它的定义是在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。一般情况下,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)

简单抽象的golang实现如下,

type ISubject interface {
   RegisterObserve(o IObserve)
   NotifyObserve(msg string)
}

type Subject struct {
   observes []IObserve
}

func (s *Subject) RegisterObserve(o IObserve) {
   if s.observes == nil {
      s.observes = make([]IObserve, 0)
   }
   s.observes = append(s.observes, o)
}

func (s *Subject) NotifyObserve(msg string) {
   for _, v := range s.observes {
      v.Update(msg)
   }
}

type IObserve interface {
   Update(msg string)
}

type Observe1 struct {
}

func (o *Observe1) Update(msg string) {
   fmt.Println("observe1 updating ", msg)
}

type Observe2 struct {
}

func (o *Observe2) Update(msg string) {
   fmt.Println("observe2 updating ", msg)
}

func TestObserve() {
   s := new(Subject)
   s.RegisterObserve(new(Observe1))
   s.RegisterObserve(new(Observe2))
   s.NotifyObserve("hello")
}

这里的关系是observe 观察 subject 的关系,两者都有接口实现,observe有一个方法处理收到的消息,subject由一些事件触发之后在自己的方法里面调用注册的observe的接收消息的方法

下面是一个实际场景,用户注册后需要1.发一个通知,2.进行推广,这里用户是被观察者,通知和推广的类注册到用户下面,当有注册行为的时候,通知观察者

type IObserve interface {
   HandleRegMsg(msg string)
}

type NotifyObserve struct {
}

func (n *NotifyObserve) HandleRegMsg(msg string) {
   fmt.Println("NotifyObserve ", msg)
}

type PromotionObserve struct {
}

func (p *PromotionObserve) HandleRegMsg(msg string) {
   fmt.Println("PromotionObserve ", msg)
}

type User struct {
   observes []IObserve
}

func (u *User) SetObserves(o []IObserve) {
   u.observes = o
}

func (u *User) Register(id int) {
   //注册相关逻辑

   msg := fmt.Sprintf("id is %d", id)
   for _, v := range u.observes {
      v.HandleRegMsg(msg)
   }
}

func TestObserve1() {
   u := new(User)
   u.SetObserves([]IObserve{new(NotifyObserve), new(PromotionObserve)})
   u.Register(1)
}

上面的这些案例是同步阻塞的,还有一些实现是异步非阻塞的