观察者设计模式
一、应用
1.1 概念
观察者设计模式是一种行为设计模式,它会允许你自定义你自己想要的订阅机制,
这个订阅机制主要是用于对象发生某些事件时能够通知多个该对象的其他对象。
这句话可能听起来有些绕口,不过我们不慌,让我们看下1.2然后在反过来看这句话,相信以你的理解能力能够瞬间融会贯通!
1.2 应用设计
让我们来举一个栗子:
假如某家报社在发布某版报纸的时候只想发给某些想看到的人:
非观察者模式:
这家报社采用大量的人力、财力挨家挨户发送该报纸,我们不妨假设情况会像下面一样:
我们可以轻易的发现,当这家报社给所有人发出报纸后只有一家反馈了比较好的看法,其他三家可能后续对这家报社的感官直接变差。
但是我们采用观察者模式会发生什么呢?
观察者模式
这家报社将报纸提供给中间商,这个中间商会看是谁关注了这个报纸,他会将该报纸只发给关注这个的人,图如下所示:
通过这个中间商,我们会在报纸出来之后发给订阅该报纸的人,而不全部发送。其实通过这两张图我们就能够轻松的发现观察者模式的用处。
1.3 模式结构
二、实现
2.1 Python实现
from random import randrange
from abc import ABC, abstractmethod
class Send(object):
_have = None
_observers = list()
def subscribe(self, observers):
"""
模拟订阅的情况
"""
if observers not in self._observers:
self._observers.append(observers)
def unsubscribe(self, observers):
"""
模拟取消订阅的情况
"""
if observers in self._observers:
self._observers.remove(observers)
def notice(self):
"""
模拟通知的情况
"""
for obs in self._observers:
obs.is_send(self)
def some_logic(self):
"""
模仿一些业务逻辑,这里主要采用对象本身的update属性进行操作
"""
self._have = randrange(0, 100)
self.notice()
class Observers(ABC):
@abstractmethod
def is_send(self):
pass
class ObserversA(Observers):
def is_send(self, send_attr):
"""
模拟满足条件发送
"""
if send_attr._have < 50:
print("A")
class ObserversB(Observers):
def is_send(self, send_attr):
"""
模拟满足条件发送
"""
if send_attr._have >= 50:
print("B")
if __name__ == '__main__':
send = Send()
obs_a = ObserversA()
send.subscribe(obs_a)
obs_b = ObserversB()
send.subscribe(obs_b)
send.some_logic()
send.some_logic()
2.2 Java实现
2.3 Golang实现
2.3.1 item.go 具体主体
package main
import "fmt"
type Item struct {
observerList []Observer
name string
inStock bool
}
func newItem(name string) *Item {
return &Item{
name: name,
}
}
func (i *Item) updateAvailability() {
fmt.Printf("Item %s is now in stock\n", i.name)
i.inStock = true
i.notifyAll()
}
func (i *Item) register(o Observer) {
i.observerList = append(i.observerList, o)
}
func (i *Item) deregister(o Observer) {
i.observerList = removeFromslice(i.observerList, o)
}
func (i *Item) notifyAll() {
for _, observer := range i.observerList {
observer.update(i.name)
}
}
func removeFromslice(observerList []Observer, observerToRemove Observer) []Observer {
observerListLength := len(observerList)
for i, observer := range observerList {
if observerToRemove.getID() == observer.getID() {
observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
return observerList[:observerListLength-1]
}
}
return observerList
}
2.3.2 item_main.go 主体
package main
import "fmt"
type Customer struct {
id string
}
func (c *Customer) update(itemName string) {
fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}
func (c *Customer) getID() string {
return c.id
}
2.3.3 obs.go 观察者
package main
type Observer interface {
update(string)
getID() string
}
2.3.4 cus.go 具体观察者
package main
import "fmt"
type Customer struct {
id string
}
func (c *Customer) update(itemName string) {
fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}
func (c *Customer) getID() string {
return c.id
}
2.3.5 main.go 运行
package main
func main() {
shirtItem := newItem("Nike Shirt")
observerFirst := &Customer{id: "123456@qq.com"}
observerSecond := &Customer{id: "78910@qq.com"}
shirtItem.register(observerFirst)
shirtItem.register(observerSecond)
shirtItem.updateAvailability()
}