python 实现 观察者模式

本文的目录地址

本文的代码地址

有时,我们希望在一个对象的状态改变时更新另外一组对象。在MVC模式中有这样一个非常常见的例子,假设在两个视图(例如,一个饼图和一个电子表格)中使用同一个模型的数据,无论何时更改了模型,都需要更新两个视图。这就是观察者设计模式要处理的问题。
观察者模式描述单个对象(发布者,又称为主持者或可观察者)与一个或多个对象(订阅者,又称为观察者)之间的发布—订阅关系。在MVC例子中,发布者是模型,订阅者是视图。然而,MVC并非是仅有的发布—订阅例子。信息聚合订阅(比如,RSS或Atom)是另一种例子。许多读者通常会使用一个信息聚合阅读器订阅信息流,每当增加一条新信息时,他们就能自动地获取到更新。
观察者模式背后的思想等同于MVC和关注点分离原则背后的思想,即降低发布者与订阅者之间的耦合度,从而易于在运行时添加/删除订阅者。此外,发布者不关心它的订阅者是谁。它只是将通知发送给所有订阅者。

软件的例子

django-observer源代码包是一个第三方Django包,可用于注册回调函数,之后在某些Django模型字段发生变化时执行。它支持许多不同类型的模型字段(CharField、IntegerField等)。
RabbitMQ可用于为应用添加异步消息支持,支持多种消息协议(比如,HTTP和AMQP),可在Python应用中用于实现发布—订阅模式,也就是观察者设计模式。

举例实现

例子使用继承实现观察者模式。首先实现一个Publisher,包含添加,删除及通知观察者等公用功能。DefaultFormatter类继承自Publisher,此类包含要被广播的数据,并在数据更新时调用通知观察者的方法。然后定义了两个观察者(HexFormatter和BinaryFormatter),观察者需要定义notify的方法及实现,以供广播者在数据更新时调用。完整代码文件observer.py

class Publisher:
    def __init__(self):
        self.observers = []

    def add(self, observer):
        if observer not in self.observers:
            self.observers.append(observer)
        else:
            print("Failed to add: {}".format(observer))

    def remove(self, observer):
        try:
            self.observers.remove(observer)
        except ValueError:
            print("Failed to remove: {}".format(observer))

    def notify(self):
        [o.notify(self) for o in self.observers]


class DefaultFormatter(Publisher):
    def __init__(self, name):
        Publisher.__init__(self)
        self.name = name
        self._data = 0

    def __str__(self):
        return "{}: '{}' has data = {}".format(type(self).__name__, self.name, self._data)

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, new_value):
        try:
            self._data = new_value
        except ValueError as e:
            print("Error: {}".format(e))
        else:
            self.notify()


class HexFormatter:
    def notify(self, publisher):
        print("{}: '{}' has now hex data = {}".format(type(self).__name__, publisher.name, hex(publisher.data)))


class BinaryFormatter:
    def notify(self, publisher):
        print("{}: '{}' has now binary data = {}".format(type(self).__name__, publisher.name, bin(publisher.data)))


def main():
    df = DefaultFormatter('test1')
    print(df)

    print()
    hf = HexFormatter()
    df.add(hf)
    df.data = 3
    print(df)

    print()
    bf = BinaryFormatter()
    df.add(bf)
    df.data = 21
    print(df)

    print()
    df.remove(hf)
    df.data = 13
    print(df)


if __name__ == '__main__':
    main()

运行结果:

DefaultFormatter: 'test1' has data = 0

HexFormatter: 'test1' has now hex data = 0x3
DefaultFormatter: 'test1' has data = 3

HexFormatter: 'test1' has now hex data = 0x15
BinaryFormatter: 'test1' has now binary data = 0b10101
DefaultFormatter: 'test1' has data = 21

BinaryFormatter: 'test1' has now binary data = 0b1101
DefaultFormatter: 'test1' has data = 13

Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/hbu_pig/article/details/80808888
今日推荐