hello,大家好,我是晴天,最近北京的流感病毒真不是开玩笑的,大家注意保重身体啊。本周我们继续学习设计模式系列之观察者模式。
什么是观察者模式
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听并被通知某一被观察对象的状态变化。当被观察对象的状态发生改变时,所有依赖于它的观察者都会收到通知,并自动更新。
这种模式的主要目标是实现对象之间的解耦,使得被观察对象和观察者对象可以独立地进行扩展和变化,而不会相互影响。观察者模式提供了一种简单而有效的机制,用于在对象之间建立一种发布-订阅机制,实现了一种松耦合的交互方式。
主要角色包括:
-
被观察者: 被观察的对象,它维护了一个观察者列表,提供了方法用于添加、删除和通知观察者。当自身状态发生变化时,会通知所有注册的观察者。
-
观察者: 观察者对象,它定义了在被观察者状态发生变化时应该执行的更新操作。每个观察者都必须实现观察者接口,该接口通常包含一个
update
方法,用于接收通知。
为什么需要观察者模式
观察者模式的核心思想是将被观察者和观察者解耦,使得它们之间的关系更为灵活。可以很方便地增加观察者和删除观察者,也可以很方便地让一个观察者订阅多个被观察者。
观察者模式跟发布订阅模式很相似,算是发布订阅模式的一种特殊情况吧,为了便于理解,下文就使用发布者和订阅者来表述被观察者和观察者。
实际场景
一个实际生活中使用观察者模式的例子------是天气预报系统。在这个系统中,气象站充当发布者(Publisher),而各个天气预报应用或网站充当订阅者(Subscriber)。
具体情景如下:
-
发布者(气象站): 气象站负责采集实时的气象数据,包括温度、湿度、风速等信息。气象站维护一个观察者列表,该列表中包含注册的各个天气预报应用或网站。
-
订阅者(天气预报应用或网站): 每个天气预报应用或网站都是观察者,它们希望及时获取气象站发布的最新气象数据,以更新用户显示的天气信息。
-
通知机制: 当气象站的气象数据发生变化时,它会遍历订阅者列表,逐个通知注册的天气预报应用或网站。每个订阅者在接收到通知后,会执行相应的更新操作,例如更新显示的天气信息。
这个例子中,观察者模式实现了气象站与天气预报应用或网站的解耦。气象站无需知道具体有哪些订阅者,而订阅者也无需了解气象站的内部实现细节。这种松耦合的设计使得系统更加灵活,可以方便地新增或删除天气预报应用或网站,而不影响其他部分的代码。
观察者模式在这种情景下非常适用,因为气象站的数据变化频繁,而各个订阅者希望能够及时获取最新的信息进行更新。
代码实战
scss
package main
import "fmt"
// 抽象层
// 发布者接口
type Publisher interface {
Follow(s Subscriber)
UnFollow(s Subscriber)
Notify()
}
// 订阅者接口
type Subscriber interface {
Update() // 接到通知,执行自己的方法
Name() string
}
// 实现层
// 具体发布者
type ConcretePublisher struct {
subscribers []Subscriber
}
// 观察者订阅
func (c *ConcretePublisher) Follow(s Subscriber) {
c.subscribers = append(c.subscribers, s)
}
// 观察者取消订阅
func (c *ConcretePublisher) UnFollow(s Subscriber) {
c.subscribers = remove(c.subscribers, s)
}
// 通知所有观察只
func (c *ConcretePublisher) Notify() {
for _, s := range c.subscribers {
s.Update()
}
}
func remove(s []Subscriber, s1 Subscriber) []Subscriber {
for i, concreteSubscriber1 := range s {
if concreteSubscriber1.Name() == s1.Name() {
s = append(s[:i], s[i+1:]...)
}
}
return s
}
// 具体订阅者
type ConcreteSubscriber struct {
name string
}
func (c *ConcreteSubscriber) Update() {
fmt.Println(c.name + "收到订阅通知")
}
func (c *ConcreteSubscriber) Name() string {
return c.name
}
// 业务逻辑层
func main() {
var publisher Publisher
publisher = &ConcretePublisher{}
var subscriber1 Subscriber
var subscriber2 Subscriber
subscriber1 = &ConcreteSubscriber{"墨迹天气"}
subscriber2 = &ConcreteSubscriber{"今日头条"}
publisher.Follow(subscriber1)
publisher.Follow(subscriber2)
publisher.Notify()
}
// 输出结果:
墨迹天气收到订阅通知
今日头条收到订阅通知
代码解释:
上述代码定义了发布者接口和订阅者接口,具体的发布者需要实现 Follow 方法来注册订阅者、UnFollow 方法来移除订阅者、Notify 来通知订阅者。具体的订阅者需要实现 Update 方法来触发接收到通知后应该做的动作。
总结
本位介绍了什么是观察者模式,实际上就是定义了一种一对多的通知模式;介绍了为什么需要观察者模式,能够实现观察者和被观察者之间的解耦随意进行订阅。
写在最后
感谢大家的阅读,晴天将继续努力,分享更多有趣且实用的主题,如有错误和纰漏,欢迎留言给予指正。 更多文章敬请关注作者个人公众号 晴天码字。 我们下期不见不散,to be continued...