持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情
众多对象之间的一对多关系是这种观察者模式的基础。 它使您能够设置订阅机制,允许其他实体在您订阅的实体上的每次事件时收到警报。Kafka、RabbitMQ、Amazon SNS 和 NATS 是实现发布者/订阅者模式(观察者的一种变体!)的发布/订阅系统的一些真实示例。
应用场景
- 在 Web 开发领域,尤其是使用 React,您听说过 Redux 用于管理应用程序的状态。 Redux 是观察者模式的实现。当你附加一个动作来更新 store 中的状态时,监听变化的组件会相应地调整它们的表示。
- 如果代码被贡献到远程存储库,CI 环境将监视它的更改并执行构建。
- 事件驱动的过程式编程用于模仿观察者设计模式。
与其他设计模式一样,这种模式允许我们定义松散链接的系统。 我们可以使用这种技术开发可维护的模块化软件。 我们还可以在事件驱动系统中实现不同参与者之间的明显分割。
组成
- 抽象被观察者:抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
- 具体被观察者:具体目标类,实现抽象中的通知方法,变更时调用观察者。
- 抽象观察者 :定义接口,包含更新自己的抽象方法,当接到具体被观察者的变化通知时被调用
- 具体观察者:实现抽象观察者的方法,这样观察到变化时进行变更自身
代码实现
// 抽象观察者
type IObserver interface {
Change(sub *Subject)
}
// 具体被观察对象(主体)
type Subject struct {
observers []IObserver
name string
}
// 添加观察者
func (s *Subject) AddObserver(o IObserver) {
s.observers = append(s.observers, o)
}
// 通知信息到观察者
func (s *Subject) Notify() {
for _, o := range s.observers {
o.Change(s)
}
}
// 被观察者发生变更时
func (s Subject) ChangeName(name string) {
s.name = name
s.Notify()
}
func NewSubject() *Subject {
return &Subject{
observers: make([]IObserver, 0),
name: "",
}
}
// 具体观察者
type Receiver struct {
name string
}
func (r *Receiver) Change(s *Subject) {
fmt.Printf("[%s] 接收到: %v\n",
r.name, s.name)
}
func NewRecevier(name string) *Receiver {
return &Receiver{name}
}
func main() {
sub := NewSubject()
r1 := NewRecevier("AAA")
r2 := NewRecevier("BBB")
r3 := NewRecevier("CCC")
sub.AddObserver(r1)
sub.AddObserver(r2)
sub.AddObserver(r3)
sub.ChangeName("名字")
}
被观察者就是主题,有三个方法:添加观察者,发生变更,通知观察者;观察者一个方法:接收主体的通知。这样无论主题多少个或者发生什么变更,只需要在变更时调用自己的通知方法。而通知方法就是观察者的接收的方法。符合开闭原则,易于扩展。且只有在运行时才建立对象之间的联系