【问题标题】:java referencing objects that are not in scopejava引用不在范围内的对象
【发布时间】:2017-06-05 16:26:03
【问题描述】:

当我的 java 项目变得更大时,总是会弹出一个问题是,是否有一种简单的方法可以引用 super 或 getParent() 无法引用的特定对象。下图应说明我当前的问题:

对于每个 FileListItem,我想建立一个新的 FileListItemController,它需要来自 ProtocolController 的方法。除了通过 mainWindow、FileListContentPanel、FileListItems 传递之外,还有其他方法可以引用 FileListItems 中 main 实例化的 ProtocolController 对象吗?


首先感谢您的所有回答。

我正在为我的项目使用模型、视图、控制模式。

单例模式听起来很有趣,但我的感觉是它不能解决我的问题。下面是一些代码来说明我的问题:

public class Main {
    public static void main(String [ ] args) {
        ProtocolController pc = new ProtocolController();
        mainWindow mw = new mainWindow();

    }
}
public class ProtocolController {
    File protocol;
    public ProtocolController(File protocol){
        this.protocol = protocol;
    }

    public void writeSomethingToProtocolFile(String something){
        // write something to th protcol file specified by the object
    }
}
public class mainWindow {
    public mainWindow(){
        FileListContentPanel flcp = new FileListContentPanel();
    }
}
public class FileListContentPanel {
    public FileListContentPanel(){
        int numListItems = 10;
        for (int i = 0; i < 10; i++) {
            FileListItem fli = new FileListItem();
            FileListItemController flic = new FileListItemController(fli);
        }
    }
}
public class FileListItemController {

    public FileListItemController(FileListItem fli){

    }
    public void addSomethingToProtocol(String something){
        // at this point I want to use a method from the ProtocolController class instantiated by the main method
    }
}

【问题讨论】:

  • @Martin 你能告诉我们main 方法和任何其他方法的伪代码,以便我们更容易理解你的应用程序的流程和为每个方法创建的实例数上面显示的类?

标签: java oop object scope


【解决方案1】:

Window 不需要了解协议。其实Panel也不需要知道协议。

使用依赖注入。


面板

由于Panel 创建了控制器,Panel 将需要对Protocol 的引用。所以你需要将协议注入到面板中。

class Panel {
    public Panel(Protocol protocol) {
        for(...) {
            Item item = new Item();
            Controller controller = new Controller(item, protocol);
        }
    }
}

我不建议像这样在构造函数中填充列表,但我保留它以便代码熟悉。

窗口

为防止Window 知道Protocol,您应该注入面板。

class Window {
    public Window(Panel panel) {
        // ...
    }
}

更新main

通过这些新更改,您将与您的类型进行如下交互:

Protocol protocol = new Protocol();
Panel panel = new Panel(protocol);
Window window = new Window(panel);

现在Window 不需要依赖Protocol


介绍工厂

我提到Panel 也不需要依赖Protocol

使用协议的是Controller;该面板仅引用协议,因此它可以将其传递给新创建的控制器。创建控制器需要该协议。

您可以引入一个工厂来处理控制器的创建。工厂将引用协议:

class ControllerFactory {
    private Protocol protocol;

    public ControllerFactory(Protocol protocol) {
        this.protocol = protocol;
    }

    public Controller newController(Item item) {
        return new Controller(item, protocol);
    }
}

Panel 现在将依赖于工厂而不是协议:

class Panel {
    public Panel(ControllerFactory factory) {
        factory = factory;

        for(...) {
            Item item = new Item();
            Controller controller = factory.newController(item);
        }
    }
}

您的新用法如下:

Protocol protocol = new Protocol();
ControllerFactory factory = new ControllerFactory(protocol);
Panel panel = new Panel(factory);
Window window = new Window(panel);

WindowPanel 都不知道该协议。

【讨论】:

    【解决方案2】:

    这看起来像是模型-视图-控制器设计模式的用例。

    您的 FileListItem 对象是模型(您需要一个新类来保存它们)。 Controller 和 View (FileListControlPanel) 都获得了对 Model 的引用。然后控制器使用模型上的方法来更改其内容,视图订阅模型的事件以显示更改。

    https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

    【讨论】:

      【解决方案3】:

      如果您只有一个FileListItemController 实例,您可以将Singleton pattern 与“延迟实例化”一起使用。

      ProtocolController 像这样实例化FileListItemController

      FileListItemController fileListItemControllerInstance = FileListItemController.getInstance();
      

      编辑

      如果每个FileListItem 引用一个FileListItemController,您可以使用Factory (Abstract Factory Pattern)

      在这种情况下,您的 ProtocolController 可以创建 FileListItemController 工厂。如果需要,您可以将 ProtocolController 引用传递给工厂。

      然后FileListItem 可以使用这个工厂来创建新的FileListItemController 实例。

      【讨论】:

      • OP 说。 对于每个 FileListItem 我想建立一个新的 FileListItemController.
      • 你是对的。我误解了似乎代表FileListItem 的多个实例引用FileListItemController 的一个实例的架构(在我看来)。
      【解决方案4】:

      对此有不同的方法。

      例如,如果您只需要一个ProtocolController 实例,则可以使用singleton pattern。然后每个FileListItemController 都能够检索相同的ProtocolController 对象。

      class ProtocolController {
      
          private static instance;
      
          private ProtocolController() { }
      
          public static ProtocolController getInstance() {
              if (instance == null) {
                  instance = new ProtocolController();
              }
              return instance;
          }
      }
      

      然后您可以从FileListItemController 中获取ProtocolController.getInstance(),然后调用所需的方法。

      【讨论】:

      • OP 说。 对于每个 FileListItem 我想建立一个新的 FileListItemController.
      • @CKing 正确。上面的示例满足了这一要求。
      • 现在您已经在编辑中解决了我之前的评论,这部分仍然需要解决:对于每个 FileListItem,我想建立一个需要来自 ProtocolController 的方法的新 FileListItemController .我要说明的一点是,在我们回答问题之前,需要从 OP 中了解很多内容,等待所有信息是明智的。
      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 2010-10-11
      • 2014-02-12
      • 2013-06-26
      • 2012-02-22
      • 2013-04-26
      • 1970-01-01
      • 2012-04-14
      相关资源
      最近更新 更多