简介
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
观察者模式中有两个主要角色:主题(Subject)和观察者(Observer)。
现在的汽车都带有手机app,一旦车子状态有问题,就会通知手机,同时汽车中控显示屏也会显示。这样显示屏和手机都同时监听着比如胎压、机油等等,一旦有问题,所有的观察者都会收到通知。
Demo
// CarObserver 观察者接口
type CarObserver interface {
breakdown(level int, info string)
}
// CarInfoCenter 主题接口
type CarInfoCenter interface {
RegisterObserver(observer CarObserver)
RemoveObserver(observer CarObserver)
NotifyObservers()
SetCarStatus(level int, info string)
}
// CarInfoCenterImpl 具体主题
type CarInfoCenterImpl struct {
observers []CarObserver
mutex sync.Mutex
info string
level int
}
func (cic *CarInfoCenterImpl) RegisterObserver(observer CarObserver) {
cic.mutex.Lock()
defer cic.mutex.Unlock()
cic.observers = append(cic.observers, observer)
}
func (cic *CarInfoCenterImpl) RemoveObserver(observer CarObserver) {
cic.mutex.Lock()
defer cic.mutex.Unlock()
for i, carObserver := range cic.observers {
if carObserver == observer {
cic.observers = append(cic.observers[:i], cic.observers[i+1:]...)
break
}
}
}
func (cic *CarInfoCenterImpl) NotifyObservers() {
cic.mutex.Lock()
defer cic.mutex.Unlock()
for _, observer := range cic.observers {
observer.breakdown(cic.level, cic.info)
}
}
func (cic *CarInfoCenterImpl) SetCarStatus(level int, info string) {
cic.info = info
cic.level = level
cic.NotifyObservers()
}
type CarDisplay struct {
}
func (c *CarDisplay) breakdown(level int, info string) {
fmt.Println("car display receive breakdown level:", level, " , info:", info)
}
type AppDisplay struct {
}
func (a *AppDisplay) breakdown(level int, info string) {
fmt.Println("app display receive breakdown level:", level, " , info:", info)
}
test
func TestObserver(t *testing.T) {
// 创建具体主题
carInfoCenter := &CarInfoCenterImpl{}
// 创建具体观察者
carDisplay := &CarDisplay{}
appDisplay := &AppDisplay{}
// 注册观察者
carInfoCenter.RegisterObserver(carDisplay)
carInfoCenter.RegisterObserver(appDisplay)
carInfoCenter.SetCarStatus(1, "胎压低,报警") // carDisplay和appDisplay都会收到通知
carInfoCenter.RemoveObserver(appDisplay) // 移除app监听
carInfoCenter.SetCarStatus(2, "燃油不足") // 只有carDisplay收到通知
}
在这个例子中,CarInfoCenter 是主题接口,定义了注册、移除和通知观察者的方法。CarObserver 是观察者接口,定义了接收更新通知的方法。CarInfoCenterImpl 是具体主题,实现了主题接口,并在车辆状态变化时通知注册的观察者。CarDisplay 和 AppDisplay 是具体观察者,实现了观察者接口,它们在接收到更新通知时输出相应的信息。
在 main 函数中,我们创建了具体主题 carInfoCenter 和两个具体观察者 carDisplay 和 AppDisplay,然后注册观察者并设置汽车状态,观察者收到相应的更新通知。之后,移除一个观察者并再次设置汽车状态,剩下的观察者继续收到通知。
通过这个例子,可以清晰地看到观察者模式的应用,其中汽车信息中心是主题,app显示器和汽车显示器是观察者,它们之间建立了一种松耦合的关系,实现了状态的动态更新。
作用和场景
解耦
观察者模式能够实现发布者和订阅者之间的解耦,使得它们可以独立变化。
动态更新
当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新,实现动态更新。
事件驱动
观察者模式常用于事件驱动系统,其中一个对象的状态变化触发一系列事件,通知所有观察者进行相应处理。
分布式事件处理系统
在分布式系统中,观察者模式可以用于构建事件处理系统,实现对象之间的通信和协同工作。
总体而言,观察者模式适用于需要实现发布-订阅机制、解耦发布者和订阅者、动态更新等场景。通过观察者模式,可以建立一种松耦合的关系,使得对象之间更加灵活、可扩展和易维护。