我正在编写一个小2D游戏,所有的游戏元素都是GameObject的子类。类游戏有一个GameObject的集合。我的问题是,当播放器执行操作时,我会遍历GameObject的集合来查找播放器前面的内容,然后我只想使用由GameObject的子类实现的接口的方法,而不使用instanceof和强制转换。
Here is a (very) simplified class-diagram of the situation
我试图实现访问者模式,但我希望函数visit()接受Activable或Obstacle作为参数,而不是TV或Wall。
下面是一个代码示例:
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) {
//...
}
...
}GameObject:
class GameObject {
public void acceptWatch(Game g) {
//Do nothing, only implemented in class TV
}
//Same with wall
...
}电视:
class TV extends Item implements Activable {
public void acceptWatch(Game g) {
//this works if watchVisit take a "TV" but not if it's a "Activable"
g.watchVisit(this);
}
public void watch() {
...
}
...
}我该如何解决这个问题?
发布于 2019-04-12 23:52:27
不是在GameObject中为watchTV()或hitWall()创建所有这些单独的方法,而是使用一个名为< Abstract >D9Abstract>的代码方法来创建带有任何公共变量(name、activatable、obstacle等)的Abstract。
然后,使您的其他对象(如TV或Wall )扩展GameObject,并使用该特定项在单击时将执行的操作覆盖doButtonOneActivity()方法。
现在,您的Game类只需在GameObject上调用doButtonOneActivity(),对象本身就会找出它需要做什么,而不必手动管理。
我希望这对你有帮助!
游戏:
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!");
}
}
}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;
}
}TV,它扩展了GameObject并填充了它需要的方法。
public class TV extends GameObject implements Serializable, IClusterable {
private static final long serialVersionUID = 1L;
public TV(String name, boolean activatable, boolean obstacle) {
super(name, activatable, obstacle);
}
@Override
public void doButtonOneActivity() {
if(isActivatable()){
// do whatever I need to do as a TV when I am activated...
}
if (isObstacle()){
// do whatever I need to do as a TV when I am activated as an obstacle...
}
System.out.println("I'm a TV and I was called. My name is: " + getName());
}
}墙,它扩展了GameObject并填充了它需要的方法。
public class Wall extends GameObject implements Serializable, IClusterable {
private static final long serialVersionUID = 1L;
public Wall(String name, boolean activatable, boolean obstacle) {
super(name, activatable, obstacle);
}
@Override
public void doButtonOneActivity() {
if(isActivatable()){
// do whatever I need to do as a Wall when I am activated...
}
if (isObstacle()){
// do whatever I need to do as a Wall when I am activated as an obstacle...
}
System.out.println("I'm a wall and I was called. My name is: " + getName());
}
}发布于 2019-04-12 23:56:35
我想你的问题很难只找到一个答案。它涉及到设计和意图,在这个领域总是有权衡,很少有明确的答案。
然而,我认为你应该看看Composite Pattern。复合模式本质上采用了一组不同的对象,并以相同的方式对待它们。它通过在所有更高级别的对象组件上实现所有接口来实现这一点,以便所有对象都继承一组通用的方法和属性。
在您的示例中,您可以将GameObject定义为您的组件,并实现Obstacle和Activatable接口。还可以添加一些辅助方法,如isObstacle和isActivatable,这样您就可以在不进行强制转换的情况下进行测试。现在你可以让访问者遍历列表,只对某些对象执行操作,这就是我认为你想要的。
https://stackoverflow.com/questions/55655161
复制相似问题