在Java中,传递对象的引用被认为是不鼓励的吗?
在Java中,传递对象的引用被认为是不鼓励的吗?
我是一个自学的程序员,和很多其他新手一样,我曾经在经典的“在表单之间传递数据”问题上苦苦挣扎过。大约一年前,当我在Java中构建我的第一个聊天应用程序时,我再次遇到了这个问题。我通过将运行中的GUI的引用传递给另一个类的构造函数来解决了这个问题,以便它可以直接操作GUI。例如:\n
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"); // 现在,我可以使用“ui.w”或“ui.w.ui.w.ui.w…”来代替“this”关键字 } }
\n我确信这是传输数据“向上流动”的最有效方法之一,但是当我在一个面向有相同问题的人的论坛上建议时,我遭到了一些指责(和一些赞扬)。那么在更大的应用程序中这样做可能会导致什么样混乱?当我看我的使用这种方法的应用程序时,我注意到它们非常务实和高效,但也有点过于有机(如果你愿意)和复杂(尤其是当有不同时间访问GUI的线程时等)。\n有没有更好的方法来做到这一点?在使用Qt时,我出于必要采取了不同的方法,但它更复杂,因为它使用了信号、槽和线程。请指点我正确的方向。谢谢。
在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. } }
上述代码可以通过使用接口进行改进。这样,可以将任何需要知道如何接收消息的内容传递给`Writer`:
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`对象就可以。如果您对接口不熟悉,请阅读/研究一下。它们非常方便,甚至是必不可少的!
在Java中传递对象的引用被认为是不鼓励的,因为这违背了关注点分离的原则。关注点分离是指将业务逻辑与表示层分离,使得业务逻辑能够独立于GUI进行测试,并且能够在不修改后端的情况下更改前端GUI。
为了实现关注点分离,有许多设计模式可以使用,其中之一就是模型-视图-控制器(Model View Controller,MVC)模式。在MVC模式中,不直接与GUI进行交互,而是直接与模型进行交互。
通过将运行中的GUI的引用传递给另一个类的构造方法,以便直接操作GUI,可以解决这个问题。以下是解决方法的示例代码:
public class GUIManipulator { private GUI gui; public GUIManipulator(GUI gui) { this.gui = gui; } public void manipulateGUI() { // manipulate the GUI using the reference gui.setText("Hello, World!"); } } public class GUI { private String text; public void setText(String text) { this.text = text; } public String getText() { return text; } } public class Main { public static void main(String[] args) { GUI gui = new GUI(); GUIManipulator manipulator = new GUIManipulator(gui); manipulator.manipulateGUI(); System.out.println(gui.getText()); // Output: Hello, World! } }
通过将GUI的引用传递给GUIManipulator类的构造方法,GUIManipulator类就可以直接操作GUI,从而实现了解耦业务逻辑和表示层的目的。这样,就可以在不修改GUI的情况下修改业务逻辑,并且可以在测试时独立于GUI进行测试。
在Java中不鼓励传递对象的引用,因为这违背了关注点分离的原则。为了解决这个问题,可以使用设计模式,如MVC模式,并将对象的引用传递给需要操作该对象的类的构造方法。这样可以实现业务逻辑与表示层的解耦,使得业务逻辑可以独立于GUI进行测试,并且可以在不修改GUI的情况下修改业务逻辑。
在Java中,将对象的引用传递给另一个对象的做法是不被鼓励的。这种做法的主要问题是耦合性。Writer类本来应该是一个通用的、可重用的写入类,能够完成工作并在需要时发送关于其工作内容的事件,但是现在它与特定的GUI类紧密耦合在一起。
如果Writer类接受监听器(listener),就像所有的Swing组件一样,就可以在多个不同的GUI中重用Writer类,或者选择更新文本区域(text area)而不是文本字段(text field)。
另一种解决方法是使用“pull”而不是“push”。即让GUI调用Writer类的方法来查询其状态,而不是让Writer类更新GUI。虽然这种方法不一定总是可行的,但通常是可行的。
我假设“pull”方法需要使用线程?这样做没有问题,但正如你所说,它并不总是可行的。不过,如果一个GUI应用程序不仅仅是一个基本的计算器或者类似的应用,那么它通常应该使用并发编程。
不一定。假设Writer类的工作是接收一个OrderItem对象,将其保存在数据库中,并返回累计的订单金额。Writer类可以将结果写入GUI中的“累计订单金额”文本字段,或者只是将结果返回给GUI,由GUI本身来更新文本字段。
哦,这样就说得通了。我想我经常这样做,但通常不是在GUI编程的上下文中。