在我的大多数Java应用程序中,我有一个Controller(Logic)类和一个GUI类。我通常需要Logic类来调用GUI类的方法,反之亦然。现在,当Logic构造GUI时,我在构造函数中传递对“this”的引用,因此GUI可以调用Logic上的方法。这是一些示例代码。
public class Logic {
private int num = 2;
private final GUI gui;
public Logic(){
gui = new GUI(this);
}
public int getNum(){
return num;
}
}
public class GUI {
private final Logic logic;
public GUI(Logic logic){
this.logic = logic;
}
public void calledLater(){
int num = logic.getNum();
}
}
我的问题是:这是创建聚合关系的最佳OO方式,还是我搞砸了我的设计?
答案 0 :(得分:4)
在您发布的设计中,您的UI与模型之间存在紧密耦合。如果构建大型/正式/严重/长寿命系统,这有点令人不悦。有一种众所周知的构建UI /模型体系结构的模式,称为Model-View-Controller,可以解决这个问题。
你是否需要担心去城镇制作MVC风格的架构真的取决于你的应用程序的环境以及你对未来的渴望。但是你应该阅读MVC并知道它存在。
顺便说一句,我在你的代码中看到一个"code smell":两个对象,A和B,每个对象都有一个彼此的引用。与循环引用相比,通常有更理想的做事方式。你可以避免这种情况,例如,对象A持有对B的引用(甚至可能“拥有”它),B通过通知或观察者模式等将感兴趣的数据推送到A。这避免了B必须有任何关于A的具体信息,甚至不得不知道它存在。 Voila,您的设计中的耦合较少,因此您最终可以获得更多的代码重用范围,以及更易于更改的脆弱系统。
Cocoa(和Cocoa Touch)中一个重要的中心设计模式是委托模式。这种模式涉及使用协议(类似于Java等其他语言中的接口)来解耦信息,事件等的生产者和消费者。
我建议您阅读Apple关于Cocoa Touch中基本设计模式的this excellent reference。
答案 1 :(得分:2)
将this
传递给UI类本身并不是问题,只要类的方法不是通过this
调用的,就像在您的示例中一样。您可以在getNum
的构造函数中调用GUI
,这应该避免:您的Logic
类可能尚未准备好返回正确的结果。
有一点需要注意的是,您将GUI
与Logic
类结合在一起,这可能是太多耦合。你应该考虑从Logic
中提取一个界面,让GUI
只与它的目标相互作用:
interface DataSourceForTheGui {
int getNum();
}
class Logic implements DataSourceForTheGui {
int getNum() {
return n;
}
}
class GUI {
private readonly DataSourceForTheGui data;
public GUI(DataSourceForTheGui data) {
this.data = data;
}
public void display() {
int k = data.getNum();
}
}
答案 2 :(得分:1)
嗯......我对GUI持有Logic实例感觉很好。毕竟,如果GUI应该使用Logic对象,它将不得不以某种方式访问它。
但是,我宁愿看到Logic NOT构建GUI。如果你真的希望模型和视图是分开的,我认为你会在某处构建Logic,并使用Logic对象构造GUI。然后,如果Logic因任何原因需要更新GUI,您应该让它生成一个事件。
在这种情况下,Logic需要有一个事件监听器列表,这样无论何时生成事件,都会通知所有事件监听器。然后GUI将Logic作为监听器注册,因此能够接收所有事件。
一些好的类是java.util.EventListener和java.util.EventObject。
但实际上,只有当Logic需要异步通信到GUI时才需要这样做。否则,只需坚持逻辑而不构建GUI。
答案 3 :(得分:0)
我会说它会起作用,但我永远不会从您的业务逻辑中引用GUI对象。
很少有其他评论:
答案 4 :(得分:0)
最好的事情(或者至少是最容易理解的)是将初始事物创建为外部类(由主类或主类本身直接调用)。所以你的代码看起来会像这样。
public class MainClass{
public static void main(String[] args){
l = new Logic();
g = new GUI(l);
l.setGUI(g);
}
public static Logic l;
public static GUI g;
}