" Ghost实例"在Java中?

时间:2017-01-18 18:49:53

标签: java swing design-patterns awt instances

我在使用不同对象的实例时遇到问题,这就是:

我一直在用Java(Swing& AWT)开发一款小游戏,我有以下几个类:

  • App.java
  • Play.java
  • Event.java
  • GameScene.java
  • MenuScene.java
  • Timer.java

其中:

  • App扩展了JFrame并且是一个具有应用程序主要功能的框架(main),这个类创建了游戏窗口,并且只存在这个JFrame

  • MenuScene和GameScene类是应用程序的场景,例如当您看到菜单并且您想要看到最高分时,它是一个场景,游戏的级别是一个场景等,但是在这种情况下,我只有两个场景,我在JPanels中表示了它们:MenuScene扩展了JPanel并创建了游戏菜单(按钮,图像等),同样适用于GameScene类,这也扩展了JPanel并创建了游戏。

  • 其他类(Play,Event,Timer)是简单的类,它们具有游戏"逻辑,键盘控制,计时器,游戏操作,并在三个全局变量中实例化GameScene课程。

一切都从App开始,创建它的一个实例,并在其构造函数中调用一个方法来创建"创建"菜单(MenuScene.java)。现在,菜单中有一个JButton,当按下"创建"游戏(GameScene.java)和这个类有一个JButton随时返回菜单...这里我有问题,因为如果我正在玩,我回到菜单游戏仍然存在,我可以输,这没有任何意义,就好像你玩,但不是看到游戏,你看到菜单,有趣的是图形部分工作得很好,即如果我按下一个按钮,它删除我拥有的东西,并快速绘制我想要的场景。这是因为Play,Timer和Event被实例化或者#34;存在"如果我没有记错的话。所以,如果我再次按下"创建游戏" JButton我会重新创建GameScene的第二个实例吗?而且对于MenuScene和GameScene来说是无限的。这个问题有方法解决吗?您认为我应该如何构建应用程序?

我给你一个最重要的课程大纲:

App.java

public class App extends JFrame {
   private JPanel rootPanel;

   public App() {
      //Define frame
      ...
      runScene(new MenuScene(this));
   }

   public void runScene(JPanel scene) {
      destroyScene();

      rootPanel.setBackground(scene.getBackground());
      rootPanel.add(scene);
      rootPane.validate();
      rootPanel.repaint();
   }

   private void destroyScene() {
      rootPanel.removeAll();
      rootPanel.revalidate();
      rootPanel.repaint();
   }


   public static void main(String[] args) { //Main
      new App();
   }
}

MenuScene.java

public class MenuScene extends JPanel {
   private App app;

   public MenuScene(App app) {
      this.app = app;
      //Define JPanel
      ...
      buttonStart.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new GameScene(app));
        }
      });
   }
}

GameScene.java

public class GameScene extends JPanel {
   private App;
   private Play;
   private Timer;
   private Event; //Define controls (keyboard)

   public GameScene(App app) {
      this.app = app;
      //Define JPanel, Play, Timer and Event
      ...
      buttonBackMenu.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            app.runScene(new MenuScene(app));
        }
      });
   }
}

Play.java

public class Play {
   private JLabel[][] x;

   public Play(JLabel[][] x) { //This matrix is important (is an reference), is instanced in GameScene, this is an problem?
      this.x = x;
      //Define others variables
   }
}

我感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我找到了一个有点特殊的解决方案,但我不知道它是否是最好的:

最好的方法是,由于GC不选择活动计时器,因此最好停止它们并将其他对象与null匹配。使用Singleton模式我有一个Frame的单个实例,同一个实例将在任何想要运行另一个场景的类(Scene)中使用,这里是一个实现:

<强> App.java

   public class App extends JFrame {
       private JPanel rootPanel;
       private static App app;

       private App() {
          super("x");
          createApp();
       }

       public static App getInstance() {
          if (app == null) {
            app = new App();
          }

          return app;
       }

       private void createApp() {
         //Define JFrame, rootPanel, buttons, etc ...
       }

       public void runScene(JPanel scene) {
          rootPanel.removeAll();

          rootPanel.add(scene);
          rootPanel.revalidate();
          rootPanel.repaint();
       }

       public static void main(String[] args) { //Main
          getInstance().runScene(new MenuScene());
       }
    }

<强> GameScene.java

    public class GameScene extends JPanel {

    private Play p;
    private Timer t;
    private Event e; //Define controls (keyboard)
    private JLabel[][] mat;

    public GameScene() {
       //Define JPanel, Matrix, Play, Timer and Event
       ...
       buttonBackMenu.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent x) {
             This method is useful to create another scene for example from another instance other than this (GameScene)
             changeScene(new MenuScene());
         }
       });
    }

    public void changeScene(JPanel scene) {
        e.removeKeyDispatcher(); //You must create a method that allows you to move the event key dispatcher
        t.stopAllTimers(); //You must create a method to stop all timers, or any object that is active.
        t = null;
        e = null;
        p = null;
        //If you have more active objects and work with other instances of other classes they should be "broken" or "stopped" and then match their instance to null
        App.getInstance().runScene(scene);
    }

    //Optional...
    public JLabel[][] getMat() {
       return mat;
    }
 }

Play.java,Event.java,Timer.java(X)

public class X {

   private GameScene g;
   private JLabel[][] mat;

   public X(GameScene g) {
      this.g = g;
      //I would use the instance of the class I need to access the variables I'm going to use, for example:
      this.mat = g.getMat();
   }
}