我的Java Game项目中是否过度使用了静态功能? [英] Overuse of static in my Java Game project?

查看:52
本文介绍了我的Java Game项目中是否过度使用了静态功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在用Java开发一个小平台,为此我编写了自己的游戏引擎,名为盆景.现在我问自己一个问题:我是否过度使用了静态方法?".

I am currently developing a little platform in Java and I wrote my own game engine for it called Bonsai. Now I'm asking myself the question "Did I overuse statics?".

一方面,这非常方便,因为我不必在每个类(例如地图或玩家)中都保留对游戏实例的引用.另一方面...我已经不得不取消applet的支持,因为那里的所有静态内容都很麻烦.

On the one hand it's very convenient since I don't have to keep a reference to the game instance in each class like the map or the player. On the other hand... I have already had to strip out applet support since it was very buggy with all that static stuff in there.

所以我的问题是,由于您可能比我更有经验的Java程序员,我应该摆脱所有的静态知识吗?如果是的话,什么是达到这样的效果的有效方法:

So my question is, since you may be much more experienced Java programmers than I, should I get rid of all the statics? And if yes, what would be an effective approach to get to something like this:

public void draw(Graphics2D) {
  if (this.game.time() > this.timer) {
    this.game.image.draw(this.tiles[this.game.animation.get("tileAnim")], x, y, null)
  }
}

代替:

public void draw(Graphics2D) {
  if (Game.time() > this.timer) {
    Image.draw(this.tiles[Animation.get("tileAnim")], x, y, null)
  }
}

甚至在地图编辑器中更糟:

or even worse in the map editor:

   public void control() {
     if(this.map.game.input.keyPressed(...)) {
       this.map.game.sound.play(...);
     }
   }

编辑
根据答案,我决定创建一个GameObject类,该类为每个组件提供包装方法.地图,玩家等,然后从中子类化,这样,我所有this.game调用都隐藏在场景的后面,并且在正面看起来仍然不错:

EDIT
Based on the answers I decided to have an GameObject class which provides wrapper methods for each component. Map, player etc. then subclass from it, this way I all the this.game calls are hidden behind the scens an it still looks nice on the frontside:

public class GameObject {
    private Game game;

    public GameObject(Game g) {
        game = g;
    }

    public Game Game() {
        return game;
    }

    public GameAnimation Animation() {
        return game.animation;
    }

    public GameInput Font() {
        return game.input;
    }

    // ...

    public long Time() {
        return game.time();
    }
}

现在代码如下:

public class Player() {
    public Player(Game g, int xpos, int ypos) {
      super(g);
      // do other stuff
    }

    public void jump() {
      // jump code
      Sound().play("jump");
    }
}

还是Java更糟糕?

EDIT2
好的,我已经在使用方法调用时遇到了问题,编译器给了我错误,因为它无法在原始版本中找到我的子类Game的方法,我想我要在这里使用纯字段.

EDIT2
Ok I'd already run into problems using method calls the compiler is giving me errors since it can't find methods of my subclassed Game in the original one, i think I'm jsut gonna use plain fields here.

EDIT3
好的,我的GameObject类现在看起来像这样,一切都再次正常运行,我可以重新实现applet支持:)

EDIT3
Ok my GameObject class now looks like this, everything works fine again and I can reimplement that applet support :)

public class GameObject {
    protected Game game;
    protected GameAnimation animation;
    protected GameFont font;
    protected GameInput input;
    protected GameImage image;
    protected GameSound sound;

    public GameObject(Game g) {
        game = g;
        animation = game.animation;
        font = game.font;
        input = game.input;
        image = game.image;
        sound = game.sound;
    }
    }

推荐答案

首先.

您不必摆脱所有静态代码,因为那样会使它在纸上"更好.

You don't have to get rid of all your static code just because that would make it better on "paper".

您真的必须了解实例代码(非静态)和类代码(静态)之间的区别

You really have to understand what the difference is between instance code (non-static) and class code (static)

静态代码(类方法/属性)在方法/属性不需要类的实例运行时使用.一个很好的例子是图像绘制方法: Image.draw()

static code (class methods/attributes) is used when the methods/attributes do no need an instance of the class to work. A very good example is the image draw method: Image.draw()

实例方法/属性可用于保持给定对象的状态,该状态必须与其他对象中的数据分开.

instance methods/attributes are useful to keep state of a given object which must be kept separate from data in other objects.

例如,如果您的游戏中有 Player 类,并且有两个实例 player1 player2 ,则每个实例都有意义有自己的分数:

For instance, if you have Player class in your game and you have two instances player1 and player2 it makes sense each of them to have their own score:

 public class Player {
     private int score;
     private String name;
     etc.....
 }

 Player one = new Player("Player 1");
 display( one.score );

 Player two = new Player("Player 2");
 display( two.score );

无需创建工件来保持每个玩家的得分(例如将它们放在每个索引都是属性的数组中,并使该数组为静态等)等

Instead of having to create artifacts to keep each player score (like putting them in arrays where each index is an attribute and make that array static etc. etc.)

第二次

您可以通过为对象分配适当的属性并以正确的方式执行封装,来减少您提到的 object1.atr2.other.next.etc 的构造.

You may reduce the constructs you mentioned object1.atr2.other.next.etc by assigning to objects appropriate attributes and performing encapsulation in the right way.

如果对象 b 需要访问另一个 a 的第N个元素,则该属性很可能属于对象 b 而不是 a 或可能的对象 a 应该提供一种避免暴露其内部的方法.

If a object b needs to access the N'th element of another a it is likely that said attribute belongs to the object b instead of a or probably that object a should provide a method to avoid exposing it's internals.

它甚至使代码更易于阅读:

It even makes the code easier to read:

即.

public void draw(Graphics2D) {
  if( this.game.needsDrawing() ) {
       this.game.draw();
  }
}

代替:

public void draw(Graphics2D) {
    if (this.game.time() > this.timer) {
        this.game.image.draw(this.tiles[this.game.animation.get("tileAnim")], x, y, null)
    }
}

再次,这取决于情况,在某些情况下您可能不需要实例(同样,例如Image的draw()实用程序方法)

Again, it depends on the situation, there might be scenarios where you don't need an instance (again, like the draw() utility method of Image)

最后.

实例方法允许您使用多态性,而类方法则不允许(至少在Java和其他静态类型的语言中).

Instance methods allow you to use polymorphism while class methods do not (at least, in Java and other statically typed languages).

因此,如果您的代码是实例代码,则可能会受益于使用运行时委托和多态性.以状态模式为例,如果所有代码都是静态的,则无法使用它,但是您可以可以使用实例代码:

So, you may benefit from using runtime delegation and polymorphism if your code is instance code. Take for instance the State pattern you can't use it if all your code is static, but you can with instance code:

class Game {
     GameState state = GameState.getInitialState( this );

     void run() {
         while( state.alive ) {
              do X Y Z
              state.updateState();
          }
     }
  }


class GameState {
    Game context;
    static GameState getInitialState( Game g ) {
        return new StartGameState(g);
    }
    void updateState();
}

class StartGameState {
     void updateState() {
         if( this.context.someCondition() ) {
             this.context.state = new MidGameState();
         }
     }
 }


class MidGameState {
     void updateState() {
         if( this.context.someOtherCondition() ) {
             this.context.state = new EndGameState();
         }
     }
 }

class EndGameState {
     void updateState() {
        Game over... 
     }
 }

再一次,仅当这在对象定向方面有意义时,例如对象是否具有需要数据的属性?如果不是,最好保持该部分代码不变.

And once again, only if this make sense in terms of object orientation, like does the object have attributes whose data is required? If not it may be good to keep that section of code static.

所有这些概念(封装,多态性,抽象,继承等)都是OO技术的本质,在

All these concepts (encapsulation, polymorphism, abstraction, inheritance, etc) are the very nature of OO technology and covered in OOA/D while they may seem like syntactic sugar (and most of the times they are) your experience will tell you when you should have something as class code and when as instance code.

这篇关于我的Java Game项目中是否过度使用了静态功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆