观察者模式
定义
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
优点
- 解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。
- 建立一套触发机制。
缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
场景
- 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
- 事件多级触发场景。
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制。
代码
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 ConcreteObserver struct { ID int Time time.Time } type ConcreteSubject struct { Observers sync.Map } func (e *ConcreteObserver) NotifyCallBack(event Event) { fmt.Println(fmt.Sprintf("Recieved:%d after %v\n", event.Data, time.Since(e.Time))) } func (e *ConcreteSubject) AddListener(obs Observer) { e.Observers.Store(obs, struct{}{}) } func (e *ConcreteSubject) RemoveListener(obs Observer) { e.Observers.Delete(obs) } func (e *ConcreteSubject) 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 = j, i+j { out <- i } }() return out }
package Observer import ( "sync" "testing" "time" ) func TestFib(t *testing.T) { n := ConcreteSubject{Observers: sync.Map{}} obs1 := ConcreteObserver{ ID: 1, Time: time.Now(), } obs2 := ConcreteObserver{ ID: 1, Time: time.Now(), } n.AddListener(&obs1) n.AddListener(&obs2) for x := range Fib(10) { n.Notify(Event{Data: x}) } }
其他设计模式
设计模式Git源代码
00简单工厂模式
01工厂方法模式
02抽象工厂模式
03外观模式
04建造者模式
05桥接模式
06命令模式
07迭代器模式
08模板模式
09访问者模式
10备忘录模式
11责任链模式
12中介模式
13原型模式
14状态模式
15策略模式
16享元模式
17组合模式
18解释器模式
19单例模式
20适配器模式
21代理模式
22装饰器模式
23观察者模式