我正在编写一个2D游戏,所有游戏元素都是GameObject的子类。 Game类具有GameObject的集合。我的问题是,当玩家执行一个动作时,我会遍历GameObject的集合以查找玩家面前的内容,然后我只想使用由GameObject子类实现的接口的方法,而不使用instanceof和cast。 >
Here is a (very) simplified class-diagram of the situation
我尝试实现访客模式,但我希望函数visit()
接受Activable
或Obstacle
作为参数,而不接受TV
或{{ 1}}。
下面是一个代码示例:
Wall
GameObject:
class Game {
private ArrayList<GameObject> gameObjects;
...
public void actionPerformed(...) {
GameObject current;
//find the focused Game object
...
//What's easiest but I don't want
if(gameObjects instanceOf Obstacle) {
((Obstacle) current).aMethod()
...
} else if (gameObjects instanceOf Activable) {
((Activable) current).activate()
...
}
...
//What visitor allow me
public void watchVisit(TV tv) {
tv.watch();
}
public void hitVisit(Wall w) {
//...
}
//What I want
public void activableVisit(Activable a) {
a.activate();
}
public void walkVisit(Obstacle o) {
//...
}
...
}
电视:
class GameObject {
public void acceptWatch(Game g) {
//Do nothing, only implemented in class TV
}
//Same with wall
...
}
我该如何解决这个问题?
答案 0 :(得分:0)
不是在watchTV()
中为hitWall()
或GameObject
制作所有这些单独的方法,而是在GameObject
Abstract
上加上任何公共变量({{ 1}},name
,activatable
等)和一种称为obstacle
的{{1}}方法。
然后使您的其他对象(例如Abstract
或doButtonOneActivity()
扩展TV
并用单击该特定项目时所做的任何操作覆盖Wall
方法。
现在,您的GameObject
类可以只在doButtonOneActivity()
上调用Game
,对象本身可以弄清楚它需要做什么,而不必手动进行管理。
希望对您有帮助!
游戏:
doButtonOneActivity()
GameObject,它是Abstract。
GameObject
电视,它扩展了GameObject并填写了所需的方法。
public class Game implements Serializable, IClusterable {
private static final long serialVersionUID = 1L;
private ArrayList<GameObject> gameObjects;
public void actionPerformed(GameObject current) {
// Let the object do whatever it's supposed to do on button press, in either case.
current.doButtonOneActivity();
if(current.isActivatable()){
// Do whatever extra thing you need to do if this one is Activatable...
System.out.println("Hey, this thing is activatable!");
} else if (current.isObstacle()){
// Do something an obstacle needs you to do
System.out.println("Hey, this thing is an obstacle!");
}
}
}
The Wall,它扩展了GameObject并填写了所需的方法。
public abstract class GameObject implements Serializable, IClusterable {
private static final long serialVersionUID = 1L;
public String name;
private boolean activatable;
private boolean obstacle;
public GameObject(String name, boolean activatable, boolean obstacle) {
super();
this.name = name;
this.activatable = activatable;
this.obstacle = obstacle;
}
public abstract void doButtonOneActivity();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isActivatable() {
return activatable;
}
public void setActivatable(boolean activatable) {
this.activatable = activatable;
}
public boolean isObstacle() {
return obstacle;
}
public void setObstacle(boolean obstacle) {
this.obstacle = obstacle;
}
}
答案 1 :(得分:0)
我认为很难找到您问题的一个答案。它涉及设计和意图,并且在该空间中总是存在折衷,很少有明确的答案。
但是我认为您应该看看Composite Pattern。合成模式本质上采用一组不同的对象,并以相同的方式对待它们。它是通过在所有更高级别的对象Component上实现所有接口来实现的,以便所有对象都继承一组通用的方法和属性。
在您的示例中,您可以将GameObject
定义为组件,并同时实现Obstacle
和Activatable
接口。还添加一些辅助方法,例如isObstacle
和isActivatable
,以便您无需进行转换即可进行测试。现在,您可以让访问者浏览列表,并且只对某些对象执行操作,这正是我认为的目标。