将此传递给构造函数

时间:2011-12-08 01:33:43

标签: java oop constructor this aggregation

在我的大多数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方式,还是我搞砸了我的设计?

5 个答案:

答案 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类可能尚未准备好返回正确的结果。

有一点需要注意的是,您将GUILogic类结合在一起,这可能是太多耦合。你应该考虑从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对象。

  • 我会回答评论。你想做什么?
  • 您的用户应该指示您的GUI,并且GUI应该正确地指示Logic执行它需要做的事情,并将结果返回给GUI。

很少有其他评论:

  • 我将使您的Logic num成员保持不变,因为它不会改变
  • 如果您没有为GUI更改Logic对象,则没有理由将其传递给构造函数。
  • 如果您想更改您的Logic对象,我会在您的GUI类中创建一个名为Logic的属性,以便您可以访问它并在必要时进行更改。
  • 如果您真的想要获得幻想,您可以将数据访问层(业务逻辑)保存在与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;

}