Golang设计模式——23观察者模式
观察者模式
定义
观察者模式(又被称为发布-订阅(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观察者模式