在观察者模式中有两个角色“主题对象”,“观察者”,主题对象的数据变化会及时的通知到观察者对象。就比如每个人手机上订阅了抖音视频,在抖音有新消息更新时会推送到每个订阅者的手机上。
观察者模式要符合如下几点:
1、主体对象变化要通知所有的观察者对象
2、主题对象中要提供观察者对象注册和取消注册的方法
3、只有注册了的对象才会收到主题对象的数据变更通知,取消注册后不再收到通知
实现思路:
主题对象中维护一个观察者数组,当添加一个观察者对象时把它添加到主题对象维护的观察者数组中,当一个观察者对象取消订阅时就将其从观察者数组中去除。主题对象有数据变更时遍历观察者数组中的对象,并调用其update()函数通知观察者。
观察者模式的类图如下:
代码如下:
subject接口——被观察对象
type subject interface {
Register(Observer)
Deregister(Observer)
NotifyAll(string)
}
advertiser对象实现subject接口
type Advertiser struct {
name string
observers []Observer
}
func (advertiser *Advertiser) Register(observer Observer) {
advertiser.observers = append(advertiser.observers, observer)
}
func (advertiser *Advertiser) Deregister(observer Observer) {
for i := 0; i < len(advertiser.observers); i++ {
if advertiser.observers[i].GetName() == observer.GetName() {
advertiser.observers = append(advertiser.observers[:i], advertiser.observers[i+1:]...)
}
}
}
func (advertiser *Advertiser) NotifyAll(ad string) {
for _, observer := range advertiser.observers {
observer.UpdateAd(ad)
}
}
func (advertiser *Advertiser) SetName(name string) {
advertiser.name = name
}
func (advertiser *Advertiser) GetName() string {
return advertiser.name
}
观察者接口observer:
type Observer interface {
UpdateAd(string)
GetName()string
SetName(string)
}
cellphone对象实现observer接口
type Cellphone struct {
name string
adMessage string
}
func (c *Cellphone) UpdateAd(ad string) {
c.adMessage = ad
c.ShowPhoneAd()
}
func (c *Cellphone) GetName() string {
return c.name
}
func (c *Cellphone) SetName(name string) {
c.name = name
}
func (c *Cellphone)ShowPhoneAd() {
fmt.Println("Phone name: ", c.name, " Ad: ", c.adMessage)
}
computer对象实现observer接口
type Computer struct {
name string
adMessage string
}
func (c *Computer) UpdateAd(ad string) {
c.adMessage = ad
c.ShowComputerAd()
}
func (c *Computer) GetName() string {
return c.name
}
func (c *Computer) SetName(name string) {
c.name = name
}
func (c *Computer)ShowComputerAd() {
fmt.Println("Computer name: ", c.name, " Ad: ", c.adMessage)
}
调试代码如下:
hwPhone := &observer.Cellphone{}
hwPhone.SetName("mate50")
hwComputer := &observer.Computer{}
hwComputer.SetName("matebook")
advertiser := observer.Advertiser{}
advertiser.SetName("douyin")
advertiser.Register(hwPhone)
advertiser.Register(hwComputer)
advertiser.NotifyAll("是兄弟就来砍一刀")
fmt.Println("\n除去iphone")
advertiser.Deregister(hwComputer)
advertiser.NotifyAll("羊了个羊")
调试结果: