Java:访问资源与Demeter定律

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (20)

概观

在我的(Android)Java游戏中,我有一个名为resources的类。顾名思义,这个类拥有游戏的资源。我所有的OpenGL对象(Sprites)都是在这里创建的

它看起来像下面这样(显然,与真实项目中出现的相比,这是一个简化的版本):

public class Resources {

    Hero hero;
    Enemy enemy;
    MenuButtons mainMenuButtons;
    Background background;
    Scene mainMenu;

    public void createObjects(){

        hero = new Hero();
        enemy = new Enemy();
        mainMenuButtons = new MenuButtons();
        background = new Background();
        mainMenu = new Scene(this);

    }
}

所以,在我的mainMenu场景中,我需要访问我的对象,所以我们可能会看到类似这样的内容:

public class mainMenu implements Scene {

    Resources resources;

    public mainMenu(Resources resources){

        this.resources = resources;

    }

    @Override
    public void render(){

        resources.background.draw();
        resources.hero.draw();
        resources.enemy.draw();
        mainMenuButtons.draw();           

    }

    @Override
    public void updateLogic(){

        resources.hero.move();
        resources.enemy.move();
        resources.mainMenubuttons.animate();
    }

}

现在,上述方法只是一个方式来获得访问对象的资源 他们的方法。但是这实际上是否违反了德米特法? 如果不是,为什么不呢?如果是这样,以不违反LOD的方式访问这些对象的最佳方式是什么?

访问器?

一种选择(我排除了TBH--见下文)将accessor方法放入我的资源类中。所以我可以做这样的事情:

resources.drawBackround();

我有很多对象,我需要每个对象的每个方法/变量的访问器。不是很实际,看起来我正在编写大量额外的代码,而且最重要的是,它使得资源类可笑地变得很长,因为它充满了这些访问器。所以,我不会走这条路。

将对象传递到场景的构造函数中

当然,我也可以做这样的事情:

    hero = new Hero();
    enemy = new Enemy();
    mainMenuButtons = new MenuButtons();
    background = new Background();
    mainMenu = new Scene(hero, enemy, mainMenuButtons, background);

所以我可以简单地做到这一点:

    background.draw(); //etc....

这对于简单的场景(例如不需要很多对象的菜单系统)是可行的,但对于主游戏来说,它很快就会变成一团糟,因为我必须将引用30多个对象的引用传递给构造函数听起来不太对劲......

所以,如果有人能指出最好的方式继续下去,为什么我会非常感激。

提问于
用户回答回答于

所以,如果有人能指出最好的方式继续下去,为什么我会非常感激。

在我看来,最好的办法是保持资源类,使所有对象都是私有的,以避免违反法律并编写访问者(但不适用于您已经排除的任何对象)。

我有很多对象,我需要每个对象的每个方法/变量的访问器。不是很实际,看起来我正在编写大量额外的代码,而且最重要的是,它使得资源类可笑地变得很长,因为它充满了这些访问器。所以,我不会走这条路。

我假设许多对象是同一类。所以你不必为每个对象创建一个访问器,真的会炸掉课堂。我是一款通常拥有英雄,一个或多个敌人和许多精灵的游戏。

public class Resources {

    private Hero hero;
    private Enemy enemy;
    private MenuButtons mainMenuButtons;
    private Background background;
    private Scene mainMenu;

    public void createObjects(){

        hero = new Hero();
        enemy = new Enemy();
        mainMenuButtons = new MenuButtons();
        background = new Background();
        mainMenu = new Scene(this);

    }

    public Hero getBackground() {

        return background;
    }

    public Hero getHero() {

        return hero;
    }

    public List<Enemy> getEnemies() {

        ArrayList<Enemy> list = new ArrayList<Enemy>();
        list.add(enemy);
        list.add(next_enemy);
        return list;
    }

    public List<Sprite> getSprites() {

        ArrayList<Sprite> list = new ArrayList<Sprite>();
        list.addAll(enemy.getActiveSprites());
        return list;
    }

}

如果英雄和敌人来自同一个类,getHero()和getEnemy()也可以成为getActor()方法。getSprites()方法仅仅是一个例子。

如果这种解决方案不适合你,我还有另一个建议。

让资源类做一些工作。

public class ResourceManager {

    private Hero hero;
    private Enemy enemy;
    private MenuButtons mainMenuButtons;
    private Background background;
    private Scene mainMenu;

    public void createObjects(){

        hero = new Hero();
        enemy = new Enemy();
        mainMenuButtons = new MenuButtons();
        background = new Background();
        mainMenu = new Scene(this);

    }

    public void render(Scene scene) {

        this.background.draw();
        if (scene != mainMenu) {

            this.hero.draw();
            this.enemy.draw();
        }
        this.mainMenuButtons.draw();           

    }

    public void updateLogic(Scene scene){

        this.hero.move();
        this.enemy.move();
        this.mainMenubuttons.animate();
    }

}

然后mainMenu直接在RescourceManager类中调用逻辑方法。

public class mainMenu implements Scene {

    ResourceManager resourceManager;

    public mainMenu(ResourceManager resourceManager){

        this.resourceManager = resourceManager;
    }

    @Override
    public void render(){

        resourceManager.render(this);
    }

    @Override
    public void updateLogic(){

        resourceManager.updateLogic(this);
    }

}

我希望我的建议能够帮助你弄清楚如何继续你的项目。

用户回答回答于

可以使用依赖注入并消除您的资源类。然后你可以在你的领域调用函数,并且不会违反德米特法。

以下是使用构造函数注入的示例:

public class MainMenu implements Scene {

   Background background;
   Hero hero;  
   Enemy enemy; 
   MenuButtons buttons

    public mainMenu(Background background, Hero hero,  Enemy enemy, MenuButtons buttons){

       this.background = background;
       this.hero = hero;
       this.enemy = enemy;
       this.buttons = buttons;   
    }

    @Override
    public void render(){

        this.background.draw();
        this.hero.draw();
        this.enemy.draw();
        this.mainMenuButtons.draw();           

    }

    @Override
    public void updateLogic(){

        this.hero.move();
        this.enemy.move();
        this.mainMenubuttons.animate();
    }

}

通过依赖注入,可以将实例传递给构造函数和函数,而不是在类中“新建”它们。你需要在某处管理你的实例,并且有很多库可以为你做到这一点。Dagger是Android上流行的一款:http : //square.github.io/dagger/

扫码关注云+社区