处理多层应用程序中的通信

时间:2012-08-28 19:33:48

标签: python communication observer-pattern

我正在使用Python创建一个应用程序。

我首先设计了一个API,运行正常。 我现在正在设计我的GUI。 GUI启动一个用于执行API任务的线程。

到目前为止,我使用Observer模式处理通过不同层的通信。 基本上,沟通可以有两种类型(主要是): - GUI询问线程(以及随后的API)START / STOP - API将信息传递回线程,传播到GUI。

这是我正在讨论的当前架构的简单架构。 基本上,一个箭头表示“通知”。

Current Observer/Observable communication

我担心的是,当应用程序线程通信时,Gui和API都会收到消息,因为他们订阅了。事实是,每条消息只能由两个中的一个读取。

我要解决的问题是与ID一起发送消息。这三个元素中的每一个都有一个id,他们知道消息是给他们还是现在。 但我不确定这是否是“正确的”(理解最好的)方法。如果我将来有更多派对怎么办?

我开始考虑某种经理处理沟通,但它必须处于架构的顶层,我不知道如何进一步组织它:s。

我不是要求一个完整的解决方案,而是主要是有经验的人的想法或最佳实践;)

在这个简单的例子中,我可以继续处理多个Observer模式。 但我正在考虑将我的代码移植到服务器上。在这种情况下,我可能会为应用程序设置多个线程,并且处理API调用将变得非常不可能。

链接到我正在谈论的代码: GUIApplicationThreadApplication API

您想要查看通知和更新方法。

任何建议的Thx!

4 个答案:

答案 0 :(得分:3)

我遇到的观察者模式的一个很好的实现是Qt中的信号/槽系统。对象具有信号,并且插槽(实际上是方法)可以连接到信号。发射信号时会调用连接的插槽。

在我看来,你的一些问题可能源于你在每个物体中都有单一的沟通渠道。这迫使您在每个update方法中都有一些调度机制,并使代码非常复杂。

从Qt中获取灵感,您可以为每种消息和收件人提供不同的信号。信号代码如下:

class Signal:
    def __init__(self):
        self.subs = []

    def subscribe(self, s):
        self.subs.append(s)

    def signal(self, *args, **kwargs):
        for s in self.subs:
            s(*args, **kwargs)

例如,gui将有一个信号stop_signal,并且线程是一个处理它的方法:

def handle_gui_stop(self):
    self.console_logger.debug("Facemovie is going to stop")
    self.my_logger.debug("Facemovie is going to stop")
    self.stop_process = True
    # ...

在初始化代码的某处,我们将所有内容组合在一起:

gui.stop_signal.subscribe(thread.handle_gui_stop)

答案 1 :(得分:3)

我最近创建了一个具有类似架构的GUI应用程序(GUI线程+一个单独的工作线程),我最终以两个队列的形式(来自Queue Python模块)在线程之间创建显式协议。一个队列用于GUI发出的请求,并由工作线程使用。另一个队列用于由工作线程生成并由GUI使用的答案。

当线程之间的通信是明确的时,我发现它更清楚,你可以完全控制更新的时间和地点(GUI方法只能从GUI线程调用)。

此模型在服务器环境中的自然扩展是消息队列协议,如AMQP。

答案 2 :(得分:2)

应用程序线程必须更明确地了解通信,因为它是GUI和Application API之间的通信器。这可以通过分离来自GUI和Application API的工作集(队列)来实现。此外,应用程序线程必须能够处理传递类型的模式,其中包括命令发件人和收件人。这包括管理不同队列之间的通信(例如,GUI队列具有待处理命令,等待命令在应用程序API队列中。一旦完成,则应用程序线程将结果传递回队列之间)。每个队列本身就是观察者。

在扩展应用程序方面,在我看来,您希望将来添加更多GUI,这将通过上述请求/响应(或发送方/接收方)模式实现来处理(这就足够了)。 / p>

如果您计划添加更多层垂直而不是 horisontally ,那么您不应该使用相同的应用程序线程在新层之间进行通信。嗯,实际上它可以是相同的,但实际上它至少必须是不同的。这可以通过再次完全实现我上面描述的内容(单独的队列)来实现。通过引入动态添加队列,您将可以添加新图层(新图层只对应于新队列)。

答案 3 :(得分:0)

特别是使用GUI,我推荐另一种模式:MVC。它包含Observer模式,比单独的Observer更强大。

它解决了您的顾虑,因为它将问题分开:每个图层都有一个非常特定的角色,您可以更改其中的任何一个,只要您不更改它们之间的界面。