首先,我不知道标题是否反映了我的问题。如果你有更好的主意,我道歉并请求改变它。
现在,我遇到的问题主要是设计问题。我不确定我想要的是一个好的做法,但它很方便。
我有一个名为 IMovement 的界面。
两个类实现 IMovement : VelocityMovement , SplineMovement 。
我还有一个名为精灵的课程。 Sprite有一个 IMovement 。
最后,我有两个Sprite的子级:玩家和敌人。
我知道 播放器将始终 VelocityMovement 和
我知道 敌人 始终 SplineMovement 。
除了超级类引用IMovement之外,还有一个属于VelocityMovement或SplineMovement分别来自Player或Enemy的错误(无论是设计还是实际)?
换句话说:
Interface IMovement {
public Vector2 getPosition(int time);
}
class VeloctiyMovement implements IMovement {
public Vector2 velocity;
public Vector2 getPosition(int time) { ... }
}
class SplineMovement implements IMovement {
public Spline spline;
public Vector2 getPosition(int time) { ... }
}
class Sprite {
IMovement movement;
}
class Player extends Sprite {
public VelocityMovement velocityMovement;
public Player() {
velocityMovement = new VelocityMovement();
movement = velocityMovement;
}
}
class Enemy extends Sprite {
public SplineMovement splineMovement;
public Enemy() {
splineMovement = new SplineMovement();
movement = splineMovement();
}
}
我想在子类中使用引用的原因是方便。有一半次我需要玩家的速度场,有一半我不在乎。这种情况发生在游戏中,该方法每秒被调用大约100次。
我指出100次的原因是因为我也担心铸造是否昂贵。
示例,而不是:
// When I need the velocity
Vector2 velocity = ((VelocityMovement)player.movement).velocity;
...
// When I don't care
Vector2 position = player.movement.GetPosition(time);
...
我现在可以这样做:
Vector2 velocity = player.VelocityMovement.velocity;
...
Vector2 position = player.movement.GetPosition(time);
...
所以我的问题是:玩家是否有VelocityMovement字段而敌人有SplineMovement?或者这是一个糟糕的设计?
我想你的想法。
更新
我现在记得为什么我选择使用字段IMovement而不是使用Sprite实现IMovement(正如JacobM正确建议的那样)。
这是因为在某些情况下,Enemy可以拥有SplineMovement,而在其他情况下可以使用VelocityMovement。
虽然我错误地说“我知道敌人总是会有SplineMovement”,但我应该说,我知道敌人有VelocityMovement,我会用VelocityMovements聚集所有敌人。我希望你理解我(否则我觉得自己像个白痴)。
例如:
List<Enemy> enemies = GetAllVelocityMovementEnemies();
我这样做是因为在我的游戏逻辑中的某个地方,我想只影响拥有VelocityMovements的敌人群。
所以,虽然JacobM的答案完全有效,但这不适合我的情况。否则,我必须将Enemy与EnemyVelocityMovement和EnemySplineMovement一起继承,依此类推。
所以,对于误解,我已经确定Brian Agnew's答案是我设计中最好的答案。
哦,是的,关于铸造的警告确实是过早的优化。 ;)
答案 0 :(得分:3)
暂时不要担心优化问题。过早的优化会让你感到悲伤,这很可能是不合理的。
所以,为了回答你的问题,不要在整个层次结构中复制字段 - 这是一个维护问题,你的时间节省可以忽略不计。如果您按照DRY principle进行操作,那么您将免除很多麻烦。
让你的课程通过以下方式移动(比如说):
player.move()
否则(正如你发现的那样),你必须找到他们的IMovement
,然后施放它,然后问速度,这真的打破了封装。您的玩家/敌人类可能会有不同的move()
实施,具体取决于他们的具体情况。
您可能不需要move()
方法,但我想要证明的是,智能包含在类中,而不是在调用代码中。因此,您根本不必公开IMovement
个对象。
最后,我只会在让它工作后进行优化,和测量它以确定您有问题!
答案 1 :(得分:2)
我没有时间尝试编写代码,但是,如果您使用的语言支持泛型类型,则可以执行类似
的操作class Sprite<T extends IMovement> {
T movement;
}
class Player extends Sprite<VelocityMovement> {
}
class Enemy extends Sprite<SplineMovement>{
}
这样,当你要求玩家的移动物体时,你已经知道它是一个VelocityMovement(当然你也可以将它称为移动物)。