简体   繁体   English

java引用不在范围内的对象

[英]java referencing objects that are not in scope

one question that always pops up when my java project gets bigger is if there is an easy way of making references to a specific object thats cannot be referenced by super or getParent().当我的 Java 项目变大时,总是会出现一个问题是,是否有一种简单的方法可以引用 super 或 getParent() 无法引用的特定对象。 The following graph should illustrates my current problem:下图应该说明我当前的问题: 在此处输入图片说明

For every FileListItem I want to instatiate a new FileListItemController which needs methods from ProtocolController.对于每个 FileListItem,我想创建一个新的 FileListItemController,它需要来自 ProtocolController 的方法。 Is there a way of referencing the ProtocolController object instatiated by main in the FileListItems other than passing it on through mainWindow, FileListContentPanel, FileListItems?除了通过 mainWindow、FileListContentPanel、FileListItems 传递它之外,有没有办法在 FileListItems 中引用由 main 实例化的 ProtocolController 对象?


First thanks to all your answers.首先感谢您的所有回答。

I am using the model, view, control pattern for my project.我正在为我的项目使用模型、视图、控制模式。

The singleton pattern sounds interesting but my feeling is that it does not solve my issue.单例模式听起来很有趣,但我的感觉是它不能解决我的问题。 Here is some code to illustrate my problem:这是一些代码来说明我的问题:

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
    }
}

There are different approaches for this.对此有不同的方法。

For instance, if you only need one ProtocolController instance, you could use the singleton pattern .例如,如果您只需要一个ProtocolController实例,则可以使用单例模式 Each FileListItemController is then able to retrieve the same ProtocolController object.然后每个FileListItemController都能够检索相同的ProtocolController对象。

class ProtocolController {

    private static instance;

    private ProtocolController() { }

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

You can then get ProtocolController.getInstance() from within FileListItemController and then call the desired method.然后,您可以从FileListItemController获取ProtocolController.getInstance() ,然后调用所需的方法。

If you have only one instance of FileListItemController , you can use Singleton pattern with "Lazy instantiation".如果您只有一个FileListItemController实例,您可以使用带有“延迟实例化”的单例模式

And ProtocolController instantiates FileListItemController like this :并且ProtocolController像这样实例化FileListItemController

FileListItemController fileListItemControllerInstance = FileListItemController.getInstance();

EDIT编辑

If each FileListItem references one FileListItemController , you can use a Factory ( Abstract Factory Pattern )如果每个FileListItem引用一个FileListItemController ,则可以使用Factory抽象工厂模式

In this case, your ProtocolController can instiate a FileListItemController factory.在这种情况下,您的ProtocolController可以启动FileListItemController工厂。 You can pass ProtocolController reference to the factory if needed.如果需要,您可以将ProtocolController引用传递给工厂。

Then FileListItem can use this factory to create new FileListItemController instances.然后FileListItem可以使用这个工厂来创建新的FileListItemController实例。

This looks like a use case for Model-View-Controller design pattern.这看起来像是模型-视图-控制器设计模式的用例。

Your FileListItem objects are model (You'll need a new class to hold them).您的FileListItem对象是模型(您需要一个新类来保存它们)。 Both Controller and View ( FileListControlPanel ) get a reference to Model. Controller 和 View ( FileListControlPanel ) 都获得了对模型的引用。 Controller then uses methods on model to change its contents, and View subscribes to model's events to show the changes. Controller 然后使用模型上的方法来更改其内容,而 View 订阅模型的事件以显示更改。

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

Window doesn't need to know about the protocol. Window不需要了解协议。 In fact, Panel doesn't need to know about the protocol either.事实上, Panel也不需要了解协议。

Use dependency injection.使用依赖注入。


Panel控制板

Since Panel creates the controllers, Panel will need a reference to Protocol .由于Panel创建控制器,因此Panel将需要对Protocol的引用。 So you'll need to inject the protocol into the panel.所以你需要将协议注入面板。

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

I don't recommend populating the list in the constructor like this, but I kept it so the code is familiar.我不建议像这样在构造函数中填充列表,但我保留它以便代码熟悉。

Window窗户

To prevent Window knowing about Protocol , you should inject the panel.为了防止Window知道Protocol ,您应该注入面板。

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

Update main更新main

With these new changes, you'd be interfacing with your types as follows:通过这些新更改,您将与您的类型进行如下交互:

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

Now Window doesn't need to depend on Protocol .现在Window不需要依赖Protocol


Introduce a factory介绍工厂

I mentioned how Panel doesn't need to depend on Protocol either.我提到了Panel也不需要依赖于Protocol

It's the Controller that uses the protocol;使用协议的是Controller the panel only references the protocol so it can pass it to newly created controllers.面板仅引用协议,以便将其传递给新创建的控制器。 The protocol is needed for the creation of controllers.创建控制器需要该协议。

You could introduce a factory to handle the creation of controllers.您可以引入一个工厂来处理控制器的创建。 The factory would reference the protocol:工厂将参考协议:

class ControllerFactory {
    private Protocol protocol;

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

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

Panel would now depend on the factory instead of the protocol: Panel现在将依赖于工厂而不是协议:

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

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

Your new usage would be as follows:您的新用法如下:

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

Neither Window or Panel know about the protocol. WindowPanel都不知道该协议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM