4

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

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

到目前为止,我使用观察者模式来处理通过不同层的通信。基本上,通信可以有两种类型(主要): - GUI 要求线程(以及随后的 API)开始/停止 - API 将信息返回给线程,传播到 GUI。

这是我正在谈论的当前架构的简单架构。一个箭头基本上意味着“通知”。

当前的 Observer/Observable 通信

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

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

我开始考虑某种管理器来处理通信,但它必须位于架构的顶部,我不知道如何进一步组织它:s。

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

在这个简单的案例中,我可以继续处理多个观察者模式。但我正在考虑将我的代码移植到服务器上。在这种情况下,我可能有不止一个线程用于应用程序,处理 API 调用将变得非常不可能。

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

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

感谢您的任何建议!

4

4 回答 4

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)
于 2012-10-31T09:50:42.543 回答
3

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

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

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

于 2012-11-04T19:49:59.170 回答
2

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

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

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

于 2012-11-06T23:10:49.657 回答
0

Specially with GUIs, I recomend another pattern: MVC. It includes the Observer patterns in it and is more robust than the Observer alone.

It solves your concern because it separates concerns: each layer has a very specific role and you can change any of them, as long as you don't change the interface between them.

于 2012-11-06T12:34:38.597 回答