关于设计模式:设计模式观察者Observer模式

模式定义

定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到告诉并更新

类图

利用场景

当更改一个对象的状态可能须要更改其余对象,并且理论的对象当时未知或动静更改时,应用观察者模式

长处

1.合乎开闭准则

2.能够在运行时建设对象之间的关系

要点总结

  • 应用面向对象的形象,Observe模式使得咱们能够独立地扭转指标与观察者,从而使二者之间的依赖关系达到松耦合
  • 指标发送告诉时,无需指定观察者,告诉(能够携带告诉信息作为参数)会主动流传
  • 观察者本人解决是否须要订阅告诉,指标对象对此无所不知
  • Observer模式是基于事件的UI框架中十分罕用的设计模式,也是MVC模式的一个重要组成部分

Go语言代码实现

工程目录

observe.go

 package Observer
 ​
 import (
    "fmt"
    "sync"
    "time"
 )
 ​
 type Event struct {
    Data int
 }
 ​
 type Observer interface {
    NotifyCallback(event Event)
 }
 ​
 type Subject interface {
    AddListener(observer Observer)
    RemoveListener(observer Observer)
    Notify(event Event)
 }
 ​
 type eventObserver struct {
    ID   int
    Time time.Time
 }
 ​
 type eventSubject struct {
    Observers sync.Map
 }
 ​
 func (e eventObserver) NotifyCallback(event Event) {
    fmt.Printf("Recieved:%d after %v\n", event.Data, time.Since(e.Time))
 }
 ​
 func (e *eventSubject) AddListener(obs Observer) {
    e.Observers.Store(obs, struct{}{})
 }
 ​
 func (e *eventSubject) RemoveListener(obs Observer) {
    e.Observers.Delete(obs)
 }
 ​
 func (e *eventSubject) Notify(event Event) {
    e.Observers.Range(func(key, value interface{}) bool {
       if key == nil {
          return false
       }
       key.(Observer).NotifyCallback(event)
       return true
    })
 }
 ​
 func Fib(n int) chan int {
    out := make(chan int)
    go func() {
       defer close(out)
       for i, j := 0, 1; i < n; i, j = i+j, i {
          out <- i
       }
    }()
    return out
 }

observer_test.go

 package Observer
 ​
 import (
    "sync"
    "testing"
    "time"
 )
 ​
 func TestFib(t *testing.T) {
    //for x := range Fib(10) {
    // fmt.Println(x)
    //}
 ​
    n := eventSubject{Observers: sync.Map{}}
    obs1 := eventObserver{ID: 1, Time: time.Now()}
    obs2 := eventObserver{ID: 2, Time: time.Now()}
 ​
    n.AddListener(obs1)
    n.AddListener(obs2)
 ​
    for x := range Fib(10) {
       n.Notify(Event{Data: x})
    }
 }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理