目标:每一次天气数据变化的时候,主显示器更新数据,温度显示器只显示温度数据,并且把历史变化数据都展示出来。
思路:中间一个收发代理broker去处理订阅,发布。
broker.py
# coding=utf-8
from collections import defaultdict
class Broker(object):
def __init__(self):
self.route_table = defaultdict(list)
def subscribe(self, topic, observer):
if observer in self.route_table[topic]:
return
self.route_table[topic].append(observer)
def publish(self, topic, *args, **kwargs):
for observer in self.route_table[topic]:
observer.update(*args, **kwargs)
observer.py
# coding=utf-8
import copy
class DisplayAll(object):
def __init__(self):
self.cached = []
def update(self, dic):
self.cached.append(copy.deepcopy(dic))
self.display()
def display(self):
print '#' * 40 + ' ALL ' + '#' * 40
if len(self.cached) < 1:
print '暂无数据...'
return
dic = self.cached[-1]
assert isinstance(dic, dict)
for key, value in dic.iteritems():
print key, ': ', value
class DisplayTemperature(object):
def __init__(self):
self.cached = []
def update(self, dic):
assert isinstance(dic, dict)
self.cached.append(copy.deepcopy(dic))
self.display()
def display(self):
print '#' * 40 + ' Temper ' + '#' * 40
for dic in self.cached:
for key, value in dic.iteritems():
if key == 'temperature':
print key, ':', value
跑一下试试看:
# coding=utf-8
import time
from broker import Broker
from observer import DisplayAll, DisplayTemperature
if __name__ == '__main__':
broker = Broker()
broker.subscribe('Weather', DisplayAll())
broker.subscribe('Weather', DisplayTemperature())
# 初始化数据
dic = {
'clock': time.strftime("%Y-%m-%d %X", time.localtime()),
'temperature': 20,
'humidity': 60,
'oxygen': 10
}
broker.publish('Weather', dic)
# 更新数据
dic = {
'clock': time.strftime("%Y-%m-%d %X", time.localtime()),
'temperature': 32,
'humidity': 100,
'oxygen': 34
}
broker.publish('Weather', dic)
结果:
#################### ALL ####################
clock : 2017-09-13 11:45:41
temperature : 20
oxygen : 10
humidity : 60
#################### Temper ####################
temperature : 20
#################### ALL ####################
clock : 2017-09-13 11:45:41
temperature : 32
oxygen : 34
humidity : 100
#################### Temper ####################
temperature : 20
temperature : 32
大体实现了以上的目标。
broker维护一个route_table,大概结构如下:
route_table = {
'天气': [observer1, observer2],
'财经': [observer1, observer3],
'IT': [observer2, observer4]
}
每一次订阅,如新来一个observer5,它订阅了天气话题,route_table更新如下:
route_table = {
'天气': [observer1, observer2, observer5],
'财经': [observer1, observer3],
'IT': [observer2, observer4]
}
如果天气话题更新,则数据更新后发布一下,broker会遍历通知到各个在天气下注册过的观察者,让它们各自update一下:
def publish(self, topic, *args, **kwargs):
for observer in self.route_table[topic]:
observer.update(*args, **kwargs)
同事玮哥对观察者的描述,觉得挺有趣,如下:
观察者嘛,就是把自己的眼睛给到每一个感兴趣的话题(Topic or Subject),话题更新后,会就捏一下手上有的眼睛。
以上