我正在使用Python创建一个应用程序。
我首先设计了一个API,运行正常。 我现在正在设计我的GUI。 GUI启动一个用于执行API任务的线程。
到目前为止,我使用Observer模式处理通过不同层的通信。 基本上,沟通可以有两种类型(主要是): - GUI询问线程(以及随后的API)START / STOP - API将信息传递回线程,传播到GUI。
这是我正在讨论的当前架构的简单架构。 基本上,一个箭头表示“通知”。
我担心的是,当应用程序线程通信时,Gui和API都会收到消息,因为他们订阅了。事实是,每条消息只能由两个中的一个读取。
我要解决的问题是与ID一起发送消息。这三个元素中的每一个都有一个id,他们知道消息是给他们还是现在。 但我不确定这是否是“正确的”(理解最好的)方法。如果我将来有更多派对怎么办?
我开始考虑某种经理处理沟通,但它必须处于架构的顶层,我不知道如何进一步组织它:s。
我不是要求一个完整的解决方案,而是主要是有经验的人的想法或最佳实践;)
在这个简单的例子中,我可以继续处理多个Observer模式。 但我正在考虑将我的代码移植到服务器上。在这种情况下,我可能会为应用程序设置多个线程,并且处理API调用将变得非常不可能。
链接到我正在谈论的代码: GUI,ApplicationThread和Application API。
您想要查看通知和更新方法。
任何建议的Thx!
答案 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更强大。
它解决了您的顾虑,因为它将问题分开:每个图层都有一个非常特定的角色,您可以更改其中的任何一个,只要您不更改它们之间的界面。