python 观察者模式小demo

目标:每一次天气数据变化的时候,主显示器更新数据,温度显示器只显示温度数据,并且把历史变化数据都展示出来。

思路:中间一个收发代理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),话题更新后,会就捏一下手上有的眼睛。

以上

你可能感兴趣的:(python 观察者模式小demo)