python设计模式之观察者模式

来源:互联网 发布:mrp软件下载 编辑:程序博客网 时间:2024/05/18 01:47

python设计模式之观察者模式

意图

  • 定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新

类图

观察者类图

角色

  • 类中有一个用来存放观察者对象的容器,容器是被观察者类的核心,另外还有三个方法:attach方法是向这个容器中添加观察者对象;detach方法是从容器中移除观察者对象;notify方法是依次调用观察者对象的对应方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多
  • 观察者角色一般是一个接口,它只有一个update方法,在被观察者状态发生变化时,这个方法就会被触发调用
  • 使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑
  • 观察者接口的具体实现,在这个角色中,将定义被观察者对象状态发生变化时所要处理的逻辑

优点:

  • 观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展
  • 观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死

适用性

  • 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用
  • 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的

例子

# -*- coding=utf-8 -*-class Subject(object):    """    被观察者,这个角色可以是接口,也可以是抽象类或者具体的类,    因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多    """    def __init__(self):        self._observers = []    def attach(self, observer):        if not observer in self._observers:            self._observers.append(observer)    def detach(self, observer):        try:            self._observers.remove(observer)        except ValueError:            pass    def notify(self, modifier=None):        """        :param modifier: 可以设置不通知的观察者对象,选择性通知        :return:        """        for observer in self._observers:            if modifier != observer:                observer.update(self)class Data(Subject):    """    具体的被观察者,使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑    """    def __init__(self, name=''):        Subject.__init__(self)        self.name = name        self._data = 0    @property    def data(self):        return self._data    @data.setter    def data(self, value):        self._data = value        self.notify()class Viewer(object):    """    观察者,抽象父类    """    def update(self):        passclass HexViewer(Viewer):    """    具体的观察者角色, 在被观察者状态发生变化时,这个方法就会被触发调用,    """    def update(self, subject):        print('HexViewer: Subject %s has data 0x%x' %              (subject.name, subject.data))class DecimalViewer(Viewer):    """    具体的观察者角色,在被观察者状态发生变化时,这个方法就会被触发调用    """    def update(self, subject):        print('DecimalViewer: Subject %s has data %d' %              (subject.name, subject.data))def main():    data1 = Data('Data 1')    view1 = DecimalViewer()    view2 = HexViewer()    data1.attach(view1)    data1.attach(view2)    data1.data = 10if __name__ == '__main__':    main()# output:DecimalViewer: Subject Data 1 has data 10HexViewer: Subject Data 1 has data 0xa
原创粉丝点击