模式定义
定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到通知并更新
类图
应用场景
当更改一个对象的状态可能需要更改其他对象,并且实际的对象事先未知或动态更改时,使用观察者模式
优点
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})
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。