在侦听器的handle方法中调用控制器类的方法是否有最佳实践方法?

时间:2016-11-28 19:13:31

标签: java user-interface libgdx listener

我正在开发一款小游戏,并且想知道(匿名)侦听器中句柄方法的最佳实践。虽然我特别使用libGDX进行开发,但我的问题一般是关于java编程标准。

假设我有一个控制器控制每个包含一个阶段的屏幕类。这些阶段构建了gui,包括按钮等。我将点击侦听器添加为舞台中按钮的匿名类。因为我想在句柄方法中调用屏幕的方法甚至控制器类,所以我将从控制器到屏幕的引用传递给阶段到监听器。传承参考文献在我看来并不是一种好的做法。

或者我可以在屏幕类中获取按钮并在那里添加监听器。不过,我需要为每个按钮添加get-methods。

你能想到其他更清洁的实现方法吗?

1 个答案:

答案 0 :(得分:3)

我认为在问题的最后,你走在正确的道路上,但让我们使用一些通用(甚至不是特定于Java)的编程原则来理解为什么这是正确的方法。以下是我们的原则:

  1. 关注点分离(SoC):确保您的代码完成一件事并且做得很好。
  2. 不要重复自己(DRY):编码一次;最小化样板代码。
  3. 保持简单(KISS):它更容易阅读,更易于维护,更容易测试。
  4. 当我在libGDX中创建游戏画面时,我通常使用以下结构:

    Screen
    |- Stage
    |- ControllerReference
    \- ModelReference
    

    屏幕有一个私有舞台,只有它用于为特定画面创建布局。然后我将控制器(主要用于更改屏幕)和模型(动态游戏数据)注入屏幕,如下面的示例代码所示:

    StageScreen.java

    abstract class StageScreen implements Screen {
        protected Stage stage;
        protected Game controller;
    
        public StageScreen(Game controller) {
            this.controller = controller;
        }
    
        @Override
        public void render(float v) {
            stage.act(v);
            stage.draw();
        }
    
        @Override
        public void dispose() {
            stage.dispose();
        }
        // Snipped other methods like "hide" and "resize" which aren't relevant
    }
    

    MenuScreen.java

    class MenuScreen extends StageScreen {
        private Array<Demo> demos;
    
        public MenuScreen(Game controller, Array<Demo> demos) {
            super(controller);
            this.demos = demos;
        }
    
        @Override
        public void show() {
            stage = new Stage(new ScreenViewport());
            Gdx.input.setInputProcessor(stage);
    
            VisTable table = new VisTable();
            table.setFillParent(true);
    
            for(final Demo demo : demos) {
                table.add(new VisTextButton(demo.getName(), new ChangeListener() {
                    @Override
                    public void changed(ChangeEvent changeEvent, Actor actor) {
                        controller.setScreen(demo);
                    }
                }));
                table.row();
            }
    
            stage.addActor(table);
        }
    }
    

    所以让我们举一些例子:

    1. 是否将问题分开? 。所有屏幕都会为每个演示渲染一个按钮,并告诉控制器用户的意图。它只知道Demos有名字,他们算作屏幕。我们可以通过传递一个事件(即“UserSelectsDemoX”)而不是我们想要转换到的屏幕来使我们的控制器更抽象,但我认为这会违反KISS原则。
    2. 是否让我们自己重复? 不。所有屏幕共有的代码(舞台管理,保留对文件夹的引用)在我们的抽象类,我们的子类只包含使屏幕执行其他屏幕所不需要的代码。
    3. 这很简单吗? 是。请注意,如果您熟悉基本的libGDX类(GameStage,{{1} }),您不需要任何评论来理解此代码段的作用。我们可以使事情更通用(即创建一个控制器接口和模型接口,只显示我们的屏幕需要),但添加额外的抽象只会使代码更难理解。
    4. 希望这有助于回答您关于将听众与控制器关联起来的最佳方式的问题,并且让您认为可以应用于代码库的其他部分。