我是一名自学成才的程序员,就像我曾经在经典的“表单之间传递数据”问题上遇到的许多其他新手一样。大约一年前,当我用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时,我采用了不同的方法,但由于使用了信号,插槽和线程,因此更复杂。请指出我正确的方向。感谢。
答案 0 :(得分:4)
这种方法的主要问题是耦合。 Writer类不是一个通用的,可重用的Writer类,而是能够完成它的工作,并且如果需要的话,它可以发送有关它的功能的事件,它与这个特定的GUI紧密耦合。
如果它像所有Swing组件一样接受了侦听器,则可以在几个不同的GUI中重用Writer,或者选择更新文本区域而不是文本字段。
另一种解决方案是拉动而不是推动。您可以使用编写器的GUI调用方法来查询其状态,而不是让编写器更新GUI。这并不总是可能的,但通常是。
答案 1 :(得分:1)
我通过将对正在运行的GUI的引用传递给另一个类的构造函数来解决它,因此它可以直接操作GUI。
您希望将业务逻辑与表示层分离。您希望能够独立于gui独立测试业务逻辑。您希望能够更改前端gui,而无需修改后端。这称为Separation of Concerns。
有许多设计模式可以帮助您实现这一目标。
其中一个是Model View Controller (MVC)。
您可以直接与模型进行交互,而不是直接与GUI交互。
答案 2 :(得分: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
,它就会占用任何对象。
如果您不熟悉界面,请对其进行一些阅读/研究。它们非常方便,如果没有,至关重要!