作者:键盘武者
原文链接:https://blog.csdn.net/HierarchCharles?type=blog
观察者模式的定义
观察者模式(Observer Pattern),也称为发布-订阅(Publish-Subscribe)模式,是一种常用的设计模式,属于行为型模式。这种模式用于建立对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
观察者模式通常涉及以下两类角色:
-
主题(Subject):主题是观察者模式中的核心。它维护一系列观察者,提供用于增加或删除观察者的方法,并在其内部状态发生变化时通知所有观察者。
-
观察者(Observer):观察者订阅主题的状态变化。每个观察者都必须实现一个更新接口,以便在主题状态变化时接收更新。
观察者模式的工作流程通常如下:
- 观察者向主题注册,表明它们对主题状态的变化感兴趣。
- 主题在其内部状态发生变化时,通过调用观察者的更新方法来通知所有注册的观察者。
- 观察者收到通知后,可以相应地更新自己或执行特定操作。
观察者模式的优点包括:
- 支持广播通信:主题可以无差别地通知所有感兴趣的观察者,无需关心它们的具体类型。
- 解耦:主题不需要知道观察者的具体实现,只需要知道它实现了观察者接口。这有助于降低系统各部分之间的耦合度。
- 动态订阅:观察者可以根据需要动态地订阅或取消订阅主题。
然而,它也有一些缺点,如:
- 可能导致更新的过度调用:在某些情况下,当主题状态频繁变化时,可能会导致大量的更新通知,从而影响性能。
- 观察者与主题之间的依赖关系:虽然减少了耦合,但观察者仍然需要了解它们需要更新的内容。
观察者模式广泛应用于实现事件处理系统、GUI工具、数据监视等场景。
go实现观察值模式
在Go语言中实现观察者模式,我们可以定义两个主要的接口:Observer
和 Subject
。Observer
接口将包含一个方法,该方法在被通知时调用。Subject
接口则包含添加、删除和通知观察者的方法。以下是一个简单的实现示例:
-
Observer 接口 - 这个接口定义了一个
Update
方法,当Subject
发生变化时,该方法将被调用。 -
Subject 接口 - 这个接口定义了
Attach
,Detach
和Notify
方法。Attach
用于添加新的观察者,Detach
用于移除观察者,而Notify
用于通知所有注册的观察者。 -
具体的 Subject 实现 - 这是一个实现了
Subject
接口的具体类。它将维护观察者列表,并在状态发生变化时通知它们。 -
具体的 Observer 实现 - 实现了
Observer
接口的具体类,当收到通知时做出相应的反应。
下面是用Go实现的代码示例:
package main
import (
"fmt"
)
// Observer 接口
type Observer interface {
Update(string)
}
// Subject 接口
type Subject interface {
Attach(Observer)
Detach(Observer)
Notify()
}
// ConcreteSubject 是 Subject 的具体实现
type ConcreteSubject struct {
observers []Observer
state string
}
// Attach 方法添加新的观察者
func (cs *ConcreteSubject) Attach(o Observer) {
cs.observers = append(cs.observers, o)
}
// Detach 方法移除观察者
func (cs *ConcreteSubject) Detach(o Observer) {
var indexToRemove int
for i, observer := range cs.observers {
if observer == o {
indexToRemove = i
break
}
}
cs.observers = append(cs.observers[:indexToRemove], cs.observers[indexToRemove+1:]...)
}
// Notify 方法通知所有观察者
func (cs *ConcreteSubject) Notify() {
for _, observer := range cs.observers {
observer.Update(cs.state)
}
}
// SetState 改变状态并通知观察者
func (cs *ConcreteSubject) SetState(state string) {
cs.state = state
cs.Notify()
}
// ConcreteObserver 是 Observer 的具体实现
type ConcreteObserver struct {
id int
}
// Update 方法是观察者接收通知的方式
func (co *ConcreteObserver) Update(state string) {
fmt.Printf("Observer %d received new state: %s\n", co.id, state)
}
// 主函数
func main() {
subject := &ConcreteSubject{}
observer1 := &ConcreteObserver{id: 1}
observer2 := &ConcreteObserver{id: 2}
subject.Attach(observer1)
subject.Attach(observer2)
subject.SetState("some state")
subject.Detach(observer1)
subject.SetState("another state")
}
在这个示例中,当 ConcreteSubject
的状态发生变化时,它将通知所有已注册的 ConcreteObserver
。观察者模式在需要实现事件监听和通知机制的场景中非常有用。
go哪些框架使用了观察者模式
在Go语言中,有几个流行的框架和库使用了观察者模式,这主要体现在事件处理、消息传递、数据变更通知等方面。以下是一些常见的Go框架和库,它们在各自的功能或设计中实现了观察者模式:
-
Revel:Revel 是一个高效的Web框架,它在内部使用了观察者模式来处理诸如HTTP请求、路由事件等。Revel 允许开发者通过定义不同的处理函数来“订阅”这些事件,从而对特定事件做出响应。
-
Beego:Beego 是另一个Go语言的Web框架,它在某些方面使用了观察者模式。例如,Beego的日志系统可以看作是一个观察者,它“观察”应用中发生的各种事件,并根据日志级别和配置来记录这些事件。
-
GORM:GORM 是一个流行的Go ORM框架,它提供了Hooks功能,这可以看作是观察者模式的一种实现。开发者可以在数据库操作(如插入、更新、删除)之前或之后挂载自定义函数,这些函数相当于观察者,它们在特定事件发生时被调用。
-
Go-Micro:在微服务领域,Go-Micro 框架使用观察者模式来实现服务间的事件驱动通信。它允许服务注册事件监听器,当特定事件发生时,这些监听器会被通知。
-
nsq:nsq 是一个实时分布式消息平台,虽然不是一个框架,但它的设计充分体现了观察者模式。生产者发布消息到主题(Topic),而消费者订阅这些主题以接收消息,这正是观察者模式的典型应用场景。
这些框架和库使用观察者模式来提高模块间的解耦,允许开发者以灵活的方式响应系统内部的各种事件。观察者模式的这种使用方式提高了代码的可维护性和可扩展性。