【问题标题】:Java - Swing UI separate socket logicJava - Swing UI 分离套接字逻辑
【发布时间】:2018-12-06 00:50:39
【问题描述】:

我绝望了,我基于客户端-服务器原理用 Java 开发了一个简单的多用户聊天。我已经编写了一个基本的多线程服务器应用程序,它运行良好。我的问题是基于 Swing GUI Toolkit 的客户端。带有运行时循环的基本 UI,用于在后台接收消息。我的问题是我想将套接字逻辑与 UI 分开,这意味着在最好的情况下,我有两个不同的类,一个用于套接字运行时循环,另一个用于管理 UI。由于问题,运行时循环必须向 UI 通知/添加消息,它们相互依赖。

  • MessengerView 是我的主类,它包含了 swing ui 和所有依赖的组件。目前该类还包含套接字逻辑,但我想将它们提取到外部类中。
  • ClientRuntime 应该持有套接字逻辑的类...

我的问题是,我如何将它们分开以及如何连接它们?例如,我尝试了类似摇摆的事件,并注册了这样的方法:

addListener(MessageArrivedListener listener);
emitMessageArrivedEvent(String message);

问题是,如果事件计数增加,就会非常混乱!如前所述,我的第二个选择是将套接字逻辑和 ui 设计放在一个类中,但我认为这是一个坏主意,因为它很难为其编写单元测试或查找错误......

在我使用 C++ 的时候,我有时会使用友元类来解决这个问题,因为这样可以访问其他类的类成员!但是这个解决方案通常也很令人困惑,我发现 Java 没有这样的选择。

那么是否有任何其他可能性来保持摆动小部件和套接字逻辑之间的连接,而不将它们存储在同一个类(文件)中?

【问题讨论】:

  • The problem is, that it is very confusing if the count of events raises! 是什么意思。您是否也考虑过实现自己的侦听器?这样一来,您就可以让您的套接字逻辑在其他地方的单独线程中运行,并且只要您想通知您的 UI 发生更改,就可以提供很好的事件。
  • @Aris Yea of​​ coursd 我写了自己的听众,但正如我已经说过的,我必须写很多……对我来说,这似乎很令人困惑,因为我没有概述谁来做什么,因为我不只有一个摆动视图,例如还有一个用于登录的 ui 表单,它还通过事件连接到套接字持有类...

标签: java multithreading swing sockets user-interface


【解决方案1】:

how could I separate them and how could I connect them?

用BlockingQueue 连接它们 - 这是选择连接线程的方式时的首选。

ClientRuntime 类必须启动 2 个线程:一个从阻塞队列中获取请求并将它们发送到服务器,第二个不断地通过套接字从服务器读取消息并将它们发送到 UI 线程。 UI 线程已经为消息输入阻塞队列:它被SwingUtilities.invokeLater(Runnable); 访问。 ClientRuntime 类不直接访问 UI 队列:它调用来自 MessengerView 的方法并传递从套接字接收到的内容、二进制数组或 json 字符串,并且该 UI 方法将其转换为实际更新的 Runnable用户界面。

【讨论】:

    【解决方案2】:

    他们相互依赖

    嗯,他们真的没有。 “socket”层只关心启动、运行、发布消息和停止。

    它并不关心实际上如何完成/处理所有事情,它只是在被告知时“开始”,处理输入/输出消息,发布通知并在被要求时“停止”。

    这基本上是一种观察者模式,或者如果您愿意,也可以是生产者/消费者模式。

    所以套接字层需要定义一个它愿意使用的行为或契约的“协议”。该合约的一部分将是它“如何”通过观察者或可能通过阻塞/只读队列生成有关新消息的通知 - 这由您决定。

    UI 有点复杂,因为 Swing 是单线程的,所以你不应该用长时间运行或阻塞操作来阻塞 UI。这就是像SwingWorker 这样的东西会派上用场的地方。

    它基本上充当 UI 和套接字层可用于接收消息的机制之间的代理。消息从套接字层进入SwingWorker,SwingWorker 然后publishes 进入 UI 的事件线程,然后可以安全地更新到 UI 上

    可能以Concurrency in Swing 和Worker Threads and SwingWorker 开头

    我的问题是,我如何将它们分开以及如何连接它们?例如,我尝试了类似摇摆的事件,并注册了这样的方法: 问题是,如果事件数量增加,就会非常混乱!

    我不这么认为(恕我直言)。您要做的是专注于事件的“类”。例如,从上面,您有“生命周期”事件和“消息”事件。我首先将它们分解为两个独立的接口,因为对“消息”事件感兴趣的人可能对“生命周期”事件不那么感兴趣,这样您就可以划分观察者。

    您要尝试了解的重要概念是正确使用“接口”来定义“合同”,这将成为实现的“公共”视图,允许您根据自己的想法为不同的目的设计不同的实现改变和成长。这将代码解耦并允许您更改一部分而不会对 API 的其他部分产生不利影响

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-09
      • 2021-07-10
      • 2022-11-23
      • 2011-04-10
      • 1970-01-01
      相关资源
      最近更新 更多