4

我有两个课程:Account 和 Operator。Account 包含一个 Operator 列表。现在,每当操作员(在列表中)收到一条消息时,我想通知 Account 对象也执行一些业务逻辑。

关于如何实现这一目标,我想到了三种选择:

1) 在 Operator 内持有对容器 [Account] 对象的引用并直接调用方法。由于循环引用,并不是绝对好。

2) 使用事件。据我所知,Python 中没有内置的事件处理机制。所以,这个实现起来有点棘手。

3) 不要直接向 Operator 发送消息。相反,只操作帐户,并在它们内部,在内部,处理程序操作员。这个有点限制,因为在这种情况下,我不能将引用传递给运算符。

我想知道从架构的角度来看哪种方法最有利。你通常如何处理这个任务?

如果您能指出 Python 中的代码片段,那就太好了。

4

5 回答 5

5

你想太多了。严重地。Python 不是 C++;您的担忧在 Python 中不是问题。只需写出在您的问题域中有意义的内容。

“由于循环引用,不是绝对好。”

为什么不?循环在这里根本无关紧要。双向关系是很棒的事情。使用它们。Python 垃圾可以很好地收集它们,而无需您考虑。

您对相互(双向)关系有什么可能的问题?

“...仅操作帐户,在它们内部,在内部,处理程序运算符。这个有点限制,因为在这种情况下,我不能传递对运算符的引用。”

什么?你的操作符是 Python 对象,传递你想要的一切。所有 Python 对象(实际上)都是引用,不要担心。

操作 Operator 对象时可能遇到什么问题?

于 2009-04-29T12:15:23.200 回答
3

观察者模式没有“一刀切”的解决方案。但通常,最好定义一个 EventManager 对象,感兴趣的各方可以在其中注册某些事件并在这些事件发生时发布这些事件。它只是创建了更少的依赖关系。

请注意,您需要使用全局 EventManager 实例,这在测试期间或从一般 OO 的角度(它是一个全局变量)可能会出现问题。我强烈建议不要一直传递 EventManager,因为这会使您的代码混乱。

在我自己的代码中,注册事件的“关键”是事件的类。EventManager 使用字典(事件类 -> 观察者列表)来知道哪个事件去哪里。在通知代码中,您可以使用它dict.get(event.__class__, ())来查找您的侦听器。

于 2009-04-29T12:00:25.203 回答
3

我会为此使用事件处理。您不必自己实现它——我使用pydispatcher来处理这种事件,而且它总是工作得很好(它在内部使用弱引用,以避免循环引用问题)。

此外,如果您使用的是 gui 框架,您可能已经有一个可以挂钩的事件框架,例如PyQt有信号和槽。

于 2009-04-29T12:14:12.643 回答
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自动将 notify 的 self 参数绑定到 A。然后您可以保持对该函数的引用,而不会产生无法回收的垃圾。

最后,您始终可以将Kamaelia用于此类事情。

于 2009-04-29T12:15:39.020 回答
0

网络上到处都有观察者模式片段。可靠代码的良好来源是活动状态,例如:

http://code.activestate.com/recipes/131499/

于 2009-04-29T13:00:07.960 回答