1

我是一名自学成才的程序员,和许多其他菜鸟一样,我曾经为经典的“在表单之间传递数据”问题苦苦挣扎。大约一年前,当我用 Java 构建我的第一个聊天应用程序时,我再次遇到了这个问题。我通过将对正在运行的 GUI 的引用传递给另一个类的构造函数来解决它,这样它就可以直接操作 GUI。例如:

class GUI {
    Writer w;
    void initGUI() {
        w = new Writer(this);
    }
}

class Writer {
    GUI ui;
    public Writer(GUI ui) {
        this.ui = ui;
        ui.textBox.write("Yo");
        // now, instead of the "this" keyword, I can say "ui.w" or "ui.w.ui.w.ui.w..."
    }
}

我确信这是“上游”传输数据的最有效方式之一,但我因在论坛上为遇到同样问题的人提出这一建议而感到悲痛(和一些表扬)。那么在更大的应用程序上这样做会引起什么样的混乱呢?当我查看使用它的应用程序时,我注意到它们非常实用和高效,但也有点过于有机(如果你愿意的话)和复杂(特别是当有线程在不同时间访问 GUI 时等)。

有没有更好的方法来做到这一点?在使用 Qt 时,我出于需要采取了不同的方法,但它更复杂,因为它使用了信号、插槽和线程。请指出我正确的方向。谢谢。

4

3 回答 3

4

这种方法的主要问题是耦合。Writer 类不是一个通用的、可重用的 Writer 类,它能够完成它的工作并在需要时发送关于它所做的事情的事件,它与这个特定的 GUI 紧密耦合。

如果它接受侦听器,就像所有 Swing 组件一样,您可以在几个不同的 GUI 中重用 Writer,或者选择更新文本区域而不是文本字段。

另一种解决方案是使用拉而不是推。您可以让编写器的 GUI 调用方法来查询其状态,而不是让编写器更新 GUI。这并不总是可能的,但它经常是。

于 2012-12-09T19:17:20.177 回答
1

我通过将对正在运行的 GUI 的引用传递给另一个类的构造函数来解决它,这样它就可以直接操作 GUI。

您希望将业务逻辑与表示层分离。您希望能够独立于 gui 独立地测试您的业务逻辑。您希望能够更改前端 gui,而无需修改后端。这称为关注点分离

有许多设计模式可以帮助您实现这一目标。

其中之一是模型视图控制器(MVC)

您无需直接与 GUI 交互,而是直接与模型交互。

于 2012-12-09T19:30:46.877 回答
0

是的,Java 绝对是对象的引用传递。

但是你所做的是你Writer假设你GUI是一成不变的,这意味着它总是有一个名为textBox.

仅从外观上看,Writer不应该负责访问和操作GUI. 如果您更改 . 中的内容GUI,您还需要重新编码Writer课程。

您可以将您的代码重新编码Writer为仅向其发送一条消息,GUI因为它的职责只是告诉GUI您要写什么,而不是如何写。然后将其留给GUI处理该消息:

class GUI
{
     Writer w;
     void initGUI()
     {
        w = new Writer(this); 
     }

     void ReceiveMessage(string message)
     {
         this.textBox.text = message;
     }
}

你的Writer班级:

class Writer
{
    GUI ui;

    public Write(GUI ui)
    {
         this.ui = ui;
         // Don't send the message in the constructor.
    }

    // The program calls this function with whatever text the user enters.
    public void SendMessage(string message)
    {
        ui.ReceiveMessage(message);
        // Writer no longer depends on ui to have a textbox Element.
    }
}

上面的代码可以通过接口进行改进。这样,您可以将任何需要知道如何接收消息的内容传递给您的作者:

interface IMessageReceiver
{
    void ReceiveMessage(string message);
}

现在,你GUI变成了一个 IMessageReceiver:

class GUI implements IMessageReceiver
{
     Writer w;
     void initGUI()
     {
        w = new Writer(this); 
     }

     public void ReceiveMessage(string message)
     {
         this.textBox.text = message;
     }
}

Writer现在上课:

class Writer
{
    IMessageReceiver receiver;

    public Write(MessageReceiver receiver)
    {
         this.receiver = receiver;
         // Don't send the message in the constructor.
    }

    // The program calls this function with whatever text the user enters.
    public void SendMessage(string message)
    {
        receiver.ReceiveMessage(message);

    }
}

这里的区别是Writer不再关心它是否是GUI. 只要它IMessageReceiver知道如何接收消息,它就会接受任何对象。

如果您不熟悉接口,请对其进行一些阅读/研究。它们非常方便,如果不是,至关重要!

于 2012-12-09T19:39:06.993 回答