观察者模式是一个非常重要的设计模式.
我们先从一个故事引入。
工作日的每天5点左右,大燕同学都会给大家订饭。
然后7点左右,饭来了。
于是燕哥大吼一声,“饭来啦!”,5点钟定过饭的同学就会纷纷涌入餐厅吃饭。
这就是一个典型的观察者模式的场景。
所有订饭的同学都是观察者。一旦观察到大燕吼了一声“feeding time!”, 大家就知道该吃食了。
喜欢吃辣的就去吃辣,喜欢吃臭的就去吃臭....
那么,用python 实现一版。
class: 点饭小秘大燕, attach方法,把点饭人加入到点饭大军列表, detach 把点饭人踢掉,不让他吃饭。
class:点饭人菜菜
class:点饭人高明
# 点饭小秘书大燕class Secretary: def __init__(self): self.__name = "daisy" self.__status = "打瞌睡中" # 观察者们 observers = [] @property def status(self): return self.__status @status.setter def status(self, value): print('我擦 ' + value) self.__status = value def attach(self, observer): print('%s, 我要订饭....' % observer.name) Secretary.observers.append(observer) def detach(self, observer): print('%s, 得罪了我,定了也白订....' % observer.name) Secretary.observers.remove(observer) pass def notify(self): for observer in Secretary.observers: observer.update()# 观察者菜菜class ObserverYicai: secretary = None def __init__(self, secretary): self.__name = "yi.cai" ObserverYicai.secretary = secretary def update(self): if ObserverYicai.secretary.status == "饭来了": print('i am %s,%s' % (self.__name, '我不吃辣,我喝汤')) @property def name(self): return self.__name @name.setter def name(self, value): self.__name = value# 观察者高明class ObserverGaoming: secretary = None def __init__(self, secretary): self.__name = "gaoming" ObserverYicai.secretary = secretary def update(self): if ObserverYicai.secretary.status == "饭来了": print('i am %s,%s' % (self.__name, '臭的也挺好吃...')) @property def name(self): return self.__name @name.setter def name(self, value): self.__name = valueif __name__ == "__main__": daisy = Secretary() yicai = ObserverYicai(daisy) gaoming = ObserverGaoming(daisy) daisy.attach(yicai) daisy.attach(gaoming) daisy.status = "饭来了" daisy.notify()
运行结果:
C:\Python34\python.exe "C:\Program Files (x86)\JetBrains\PyCharm 5.0.1\helpers\pydev\pydevd.py" --multiproc --qt-support --client 127.0.0.1 --port 64162 --file C:/Users/trump/PycharmProjects/untitled/Observer/Observer.py
pydev debugger: process 184 is connectingConnected to pydev debugger (build 143.595)
yi.cai, 我要订饭....gaoming, 我要订饭....我擦 饭来了i am yi.cai,我不吃辣,我喝汤i am gaoming,臭的也挺好吃...Process finished with exit code 0
猛一看,嗯。这段代码写得不错....(自我陶醉3秒钟...)
仔细一看,其实是很想比了狗的。
为什么捏?
点饭小蜜耦合了观察者,观察者耦合了点饭小蜜.....
强耦合.....这跟我们高内聚低耦合的设计模式理念完全不符哇!!
两个观察者的代码一模一样啊,有代码强迫症的我完全受不鸟啊!!
于是,几个聪明的脑瓜GOF,俗称四人帮,想了一个模式。这个模式就叫观察者模式。
闪亮登场!
观察者(Observer)模式
观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、 源 听器(Source/Listener)模式或从属者(Dependents)模式。 -监观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在 所有观察者对象,使它们能够自动更新自己。 状态上发生变化时,会通知一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做 方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。 到这一点的设计减 系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维 少对象之间的耦合有利于持行 一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设 动的协调 计方案中重要的一种。
以上,是我抄的。
根据观察者模式,我们来重写我们的代码。
# 抽象类 抽象通知者 主题 subjectclass Subject: # 定义为抽象类 __metaclass__ = ABCMeta def __init__(self): self.__status = '' pass @abstractmethod def attach(self, observer): pass @abstractmethod def detach(self, observer): pass @abstractmethod def notify(self): pass @property def status(self): return self.__status @status.setter def status(self, value): print('我擦 ' + value) self.__status = value# 通知者 点餐小蜜大燕class Secretary(Subject): observers = [] def attach(self, observer): print('%s, 我要订饭....' % observer.name) Secretary.observers.append(observer) def detach(self, observer): print('%s, 得罪了我,定了也白订....' % observer.name) Secretary.observers.remove(observer) pass def notify(self): for observer in Secretary.observers: observer.update()# 抽象观察者 observerclass Observer: # 定义为抽象类 __metaclass__ = ABCMeta # 约束子类必须实现update方法 @abstractmethod def update(self): pass# 观察者菜菜class ObserverYicai(Observer): subject = None def __init__(self, subject): ObserverYicai.subject = subject self.__name = 'yi.cai' def update(self): if ObserverYicai.subject.status == "饭来了": print('i am %s,%s' % (self.__name, '我不吃辣,我喝汤')) @property def name(self): return self.__name @name.setter def name(self, value): self.__name = value# 观察者高明class ObserverGaoming(Observer): subject = None def __init__(self, subject): ObserverYicai.subject = subject self.__name = 'gaoming' def update(self): if ObserverYicai.subject.status == "饭来了": print('i am %s,%s' % (self.__name, '臭的也挺好吃...')) @property def name(self): return self.__name @name.setter def name(self, value): self.__name = value
if __name__ == "__main__": daisy = Secretary() yicai = ObserverYicai(daisy) gaoming = ObserverGaoming(daisy) daisy.attach(yicai) daisy.attach(gaoming) daisy.status = "饭来了" daisy.notify() print('第二天,高明得罪了大燕') daisy.detach(gaoming) daisy.notify()
运行:
C:\Python34\python.exe C:/Users/trump/PycharmProjects/untitled/Observer/Observer.py
yi.cai, 我要订饭....gaoming, 我要订饭....我擦 饭来了i am yi.cai,我不吃辣,我喝汤i am gaoming,臭的也挺好吃...第二天,高明得罪了大燕gaoming, 得罪了我,定了也白订....i am yi.cai,我不吃辣,我喝汤
谔谔谔谔谔谔谔谔谔谔.....
呃呃呃呃呃呃呃...
为什么感觉和第一版没什么区别呢...
主要原因是因为python 是弱类型语言.....于是感觉不出传接口和传实际的类有何不同...
我得再好好思考下.....
在.net 中, 微软非常优雅的使用委托和事件实现了观察者模式.
通过一个object 的sender 实现事件发送方
所有订阅过事件的对象将会通过委托收到事件发生的细节.
事件的所有细节包括在EventArgs中.
以上,观察者模式...
to be continued.