我有两个班级:帐户和运营商。帐户包含操作员列表。现在,只要操作员(在列表中)收到消息,我想通知Account对象以执行某些业务逻辑。
我想到了如何实现这一目标的三种选择:
1)将Operator内的引用保存到容器[Account]对象并直接调用方法。由于循环引用而不是绝对好。
2)使用事件。据我所知,Python中没有内置的事件处理机制。所以,这个实现起来有点棘手。
3)不要直接向操作员发送消息。相反,只在内部运行处理程序运算符,在其中运行。这个有点限制,因为在这种情况下我不能传递对运算符的引用。
我想知道从架构的角度来看哪种方法最有利。你通常如何处理这项任务?
如果你能在Python中指出片段,那就太好了。
答案 0 :(得分:5)
你过分思考这个问题。认真。 Python不是C ++;您的担忧在Python中不是问题。只需在您的问题域中编写有意义的内容。
“因为循环引用而不是绝对好。”
为什么不呢?圆形在这里根本没有意义。双向关系是很棒的事情。使用它们。 Python垃圾收集它们就好了,不需要你的任何想法。
您对相互(双向)关系有什么问题?
“...只运行帐户,在其内部运行处理程序操作符。这个有点限制,因为在这种情况下我无法传递对运算符的引用。 “
什么?你的运算符是Python对象,传递你想要的一切。所有Python对象都是(实际上)引用,不要惹恼它。
操作Operator对象有什么问题?
答案 1 :(得分:3)
Observer模式没有“一刀切”的解决方案。但通常情况下,最好定义一个EventManager对象,其中感兴趣的各方可以为某些事件注册自己并在发生这些事件时发布这些事件。它只是创建较少的依赖关系。
请注意,您需要使用全局EventManager实例,这可能在测试期间或从一般OO角度(它是全局变量)时会出现问题。我强烈建议不要一直传递EventManager,因为这会使代码混乱。
在我自己的代码中,注册事件的“关键”是事件的类。 EventManager使用字典(事件类 - >观察者列表)来知道哪个事件在哪里。在通知代码中,您可以使用dict.get(event.__class__, ())
找到您的听众。
答案 2 :(得分:3)
我会为此使用事件处理。您不必自己实现它 - 我使用pydispatcher来完成这种事件处理,并且它总是工作得很好(它在内部使用弱引用,以避免循环引用问题)。
此外,如果你使用的是gui框架,你可能已经有了一个可以挂钩的事件框架,例如PyQt有信号和插槽。
答案 3 :(得分:3)
>>> class Account(object):
... def notify(self):
... print "Account notified"
...
>>> class Operator(object):
... def __init__(self, notifier):
... self.notifier = notifier
...
>>> A = Account()
>>> O = Operator(A.notify)
>>> O.notifier()
Account notified
>>> import gc
>>> gc.garbage
[]
>>> del A
>>> del O
>>> gc.garbage
[]
您可能不了解实例方法的一件事是,在使用点语法时查找它们时会受到限制。换句话说,A.notify
会自动将通知的self参数绑定到A.然后,您可以保留对此函数的引用,而不会创建无法收集的垃圾。
最后,您可以随时使用Kamaelia来处理此类事情。
答案 4 :(得分:0)
整个网络上都有Observer模式片段。可靠代码的良好来源是活动状态,E.G: