通知容器对象:最佳实践

发布于 2024-07-17 12:31:45 字数 409 浏览 6 评论 0原文

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

我想到了如何实现此目的的三种替代方案:

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

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

3) 不要直接向操作员发送消息。 相反,仅操作帐户,以及在帐户内部的处理程序操作员。 这有点限制,因为在这种情况下我无法传递对运算符的引用。

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

如果你能指出 Python 中的片段那就太好了。

I have two classes: Account and Operator. Account contains a list of Operators. Now, whenever an operator (in the list) receives a message I want to notify Account object to perform some business logic as well.

I think of three alternatives on how to achieve this:

1) Hold a reference within Operator to the container [Account] object and call methods directly. Not absolutely good because of circular references.

2) Use events. As far as I know there is no built-in event handling mechanism in Python. So, this one is a bit tricky to implement.

3) Don't send messages to Operators directly. Instead, operate only Accounts, and within them, internally, handler operators. This one is a bit limiting because in this case I cannot pass around references to operators.

I wonder which approach is the most advantageous from the architectural point of view. How do you usually handle this task?

It would be great if you could point out snippets in Python.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

月棠 2024-07-24 12:31:45

这个你想多了。 严重地。 Python 不是 C++;而是 C++。 你的担忧在 Python 中不是问题。 只需写下在您的问题领域中有意义的内容即可。

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

为什么不? 循环性在这里根本不相关。 双向关系是伟大的事情。 使用它们。 Python 垃圾收集器可以很好地收集它们,而无需您进行任何思考。

您在相互(双向)关系中可能遇到什么问题?

“...仅操作帐户,以及其中的内部处理程序操作员。这有点限制,因为在这种情况下我无法传递对操作员的引用。

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

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

You're over-thinking this. Seriously. Python isn't C++; your concerns are non-issues in Python. Just write what makes sense in your problem domain.

" Not absolutely good because of circular references."

Why not? Circularity is of no relevance here at all. Bidirectional relationships are great things. Use them. Python garbage collects them just fine without any thinking on your part.

What possible problem do you have with mutual (birectional) relationships?

"...operate only Accounts, and within them, internally, handler operators. This one is a bit limiting because in this case I cannot pass around references to operators.
"

What? Your Operators are Python objects, pass all you want. All Python objects are (in effect) references, don't sweat it.

What possible problem do you have with manipulating Operator objects?

你不是我要的菜∠ 2024-07-24 12:31:45

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

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

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

There is no "one-size-fits-all" solution for the Observer pattern. But usually, it's better to define an EventManager object where interested parties can register themselves for certain events and post these events whenever they happen. It simply creates less dependencies.

Note that you need to use a global EventManager instance, which can be problematic during testing or from a general OO point of view (it's a global variable). I strongly advise against passing the EventManager around all the time because that will clutter your code.

In my own code, the "key" for registering events is the class of the event. The EventManager uses a dictionary (event class -> list of observers) to know which event goes where. In the notification code, you can then use dict.get(event.__class__, ()) to find your listeners.

高冷爸爸 2024-07-24 12:31:45

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

另外,如果您使用的是 GUI 框架,您可能已经有一个可以连接的事件框架,例如 PyQt 有信号和槽。

I would use event handling for this. You don't have to implement it yourself -- I use pydispatcher for exactly this kind of event handling, and it's always worked very well (it uses weak references internally, to avoid the circular reference problem).

Also, if you're using a gui framework, you might already have an event framework you can hook into, for example PyQt has signals and slots.

放飞的风筝 2024-07-24 12:31:45
>>> 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 来处理此类事情。

>>> 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
[]

One thing you may not know about instance methods is that they're bound when looked up when using the dot syntax. In other words saying A.notify automatically binds the self parameter of notify to A. You can then hold a reference to this function without creating uncollectable garbage.

Lastly, you can always use Kamaelia for this type of thing.

滥情哥ㄟ 2024-07-24 12:31:45

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

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

There are Observer pattern snippets all over the Web. A good source of reliable code is active state, E.G :

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文