sugar/ 十月 28, 2019/ python设计模式/ 0 comments

观察者模式描述单个对象(发布者,又称为主持者或可观察者)与一个或多个对象(订阅者, 又称为观察者)之间的发布—订阅关系。在MVC例子中,发布者是模型,订阅者是视图。然而, MVC并非是仅有的发布—订阅例子。信息聚合订阅(比如,RSS或Atom)是另一种例子。许多读 者通常会使用一个信息聚合阅读器订阅信息流,每当增加一条新信息时,他们就能自动地获取到 更新。
观察者模式背后的思想等同于MVC和关注点分离原则背后的思想,即降低发布者与订阅者 之间的耦合度,从而易于在运行时添加/删除订阅者。此外,发布者不关心它的订阅者是谁。它 只是将通知发送给所有订阅者。

现实生活的例子

现实中,拍卖会类似于观察者模式。每个拍卖出价人都有一些拍牌,在他们想出价时就可以 举起来。不论出价人在何时举起一块拍牌,拍卖师都会像主持者那样更新报价,并将新的价格广 播给所有出价人(订阅者)。

应用案例

当我们希望在一个对象(主持者/发布者/可观察者)发生变化时通知/更新另一个或多个对象 的时候,通常会使用观察者模式。观察者的数量以及谁是观察者可能会有所不同,也可以(在运 行时)动态地改变。
可以想到许多观察者模式在其中有用武之地的案例。本章开头已提过这样的一个案例,就是 信息聚合。无论格式为RSS、Atom还是其他,思想都一样:你追随某个信息源,当它每次更新时, 你都会收到关于更新的一个通知。

实现

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 = int(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 bin 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 = 40
    print(df)

    print()
    df.remove(hf)
    df.add(bf)
    df.data = 'hello'
    print(df)

    print()
    df.data = 15.8
    print(df)

if __name__ == '__main__':
    main()

若希望在一个对象的状态变化时能够通知/提醒所有 相关者(一个对象或一组对象),则可以使用观察者模式。观察者模式的一个重要特性是,在运 行时,订阅者/观察者的数量以及观察者是谁可能会变化,也可以改变。

Share this Post

说点什么

avatar
  Subscribe  
提醒