实现简单的观察者模式及Django中观察者模式解析

一、观察者模式介绍

概念:

  观察者模式(Observer Pattern),又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。定义了对象之间的一种一对多的依赖关系,从而使得当被观察对象状态发生变化时,自动通知其依赖对象,并且依赖对象自动更新。

解决重点:

  被观察对象的状态改变如何主动通知其依赖的对象,同时需要考虑到低耦合和易用性,保证高度协作。

如何解决:

  面向对象技术可以弱化这种依赖关系。抽象类中需要设置一个ArrayList存放所有的观察者。

优点:

  1.目标对象和观察者对象是抽象耦合的;

  2.建立了一套触发机制。

缺点:

  1.观察者模式只是主动通知了目标对象发生了变化,没有相应的机制使得观察者知道所观察的目标对象如何发生变化的;

  2.观察者和观察目标之间可能存在循环依赖,观察者模式中目标对象可能触发两者之间的循环调用,从而系统存在崩溃风险。

  3.如果目标对象存在多个直接或间接的观察者对象,主动通知所有的观察者会消耗大量的资源,花费大量时间。

场景理解:

  在众多游戏中,主角行走过程中,地图中心摄像头总是跟随主角调整视角和位置,使得主角总是处于场景的中心。主角进行行走或战斗操作时,主角的仆从根据主角的操作进行相应的跟随或战斗行为。

二、简单实现

 观察者模式结构如图,其中角色包括Subject(目标对象)、ConcreteSubject(具体目标)、Observer(观察者)、ConcreteObserver(具体观察者)。

(模式图来源:https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/observer.html)

 Python代码实现简单的观察者模式:

 1 # *-* coding:utf-8 *-*
 2 
 3 
 4 # Observer
 5 class Bob_Observer():
 6       def save(self):
 7             print('Bob:I will help you.')
 8 
 9       def com(self):
10             print('Bob:I am here to accompany you.')
11 
12 
13 # Observer
14 class Eve_Observer():
15       def save(self):
16             print('Eve:Go away. Let me save her.')
17 
18       def com(self):
19             print('Eve:Go away and let me go with her.')
20 
21 
22 # Observable
23 class Alice_Observable():
24       Bob = Bob_Observer
25       Eve = Eve_Observer
26 
27       def __init__(self,Bobobj,Eveobj):
28             self.Bob = Bobobj
29             self.Eve = Eveobj
30 
31       def call_help(self):
32             print('Alice:Help!')
33             self.Bob.save()
34             self.Eve.save()
35 
36       def call_com(self):
37             print('Alice:Who will go shopping with me?')
38             self.Bob.com()
39             self.Eve.com()
40 
41 
42 # interface
43 class Run():
44       Alice = Alice_Observable
45       def __init__(self,Aliceobj):
46             self.Alice = Aliceobj
47       def runhelp (self):
48             self.Alice.call_help()
49       def runcom (self):
50             self.Alice.call_com()
51 
52 
53 if __name__== '__main__':
54       m = Bob_Observer()
55       g = Eve_Observer()
56       h = Alice_Observable(m, g)
57       run = Run(h)
58       run.runhelp()
59       print('--- *_* ---')
60       run.runcom()

其中,Alice_Observable为目标对象,Bob_Observer为、Eve为观察者对象。

输出如下:

三、Django中观察者模式应用

GitHub链接:

https://github.com/django/django/blob/master/django/dispatch/dispatcher.py#L19

 目标对象方法:

https://github.com/django/django/blob/master/django/dispatch/dispatcher.py#L152

 1 def send(self, sender, **named):
 2         """
 3         Send signal from sender to all connected receivers.
 4         If any receiver raises an error, the error propagates back through send,
 5         terminating the dispatch loop. So it's possible that all receivers
 6         won't be called if an error is raised.
 7         Arguments:
 8             sender
 9                 The sender of the signal. Either a specific object or None.
10             named
11                 Named arguments which will be passed to receivers.
12         Return a list of tuple pairs [(receiver, response), ... ].
13         """
14         if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:
15             return []
16 
17         return [
18             (receiver, receiver(signal=self, sender=sender, **named))
19             for receiver in self._live_receivers(sender)
20         ]

观察者方法:

https://github.com/django/django/blob/master/django/dispatch/dispatcher.py#L272

 1 def receiver(signal, **kwargs):
 2     """
 3     A decorator for connecting receivers to signals. Used by passing in the
 4     signal (or list of signals) and keyword arguments to connect::
 5         @receiver(post_save, sender=MyModel)
 6         def signal_receiver(sender, **kwargs):
 7             ...
 8         @receiver([post_save, post_delete], sender=MyModel)
 9         def signals_receiver(sender, **kwargs):
10             ...
11     """
12     def _decorator(func):
13         if isinstance(signal, (list, tuple)):
14             for s in signal:
15                 s.connect(func, **kwargs)
16         else:
17             signal.connect(func, **kwargs)
18         return func
19     return _decorator

将目标对象与观察者对象连接,以获取信号:

connect(self, receiver, sender=None, weak=True, dispatch_uid=None)

将目标对象与观察者对象之间的连接断开:

disconnect(self, receiver=None, sender=None, dispatch_uid=None)

使用观察者模式给项目带来的好处:

1.可以尽量多的使用继承,从而项目扩展性更强;

2.将所有的观察者抽象为观察者类,更加容易控制;

3.目标对象和观察者对象抽象耦合,符合低耦合的设计原则。

4.表示层和数据数据层分离,层间抽象接口,定义了稳定的连接、断开连接、消息更新机制,不同的表示层可以定义不同的具体观察者对象。

5.灵活实现了广播机制。

猜你喜欢

转载自www.cnblogs.com/yaoone/p/9827549.html