[英]Where to put a interface related variable that it is not static and final
我正处于游戏开发的初期。 这是某种基于回合的游戏,例如《战锤》或《魔兽争霸》。 有些生物可以再生他们遭受的伤害,并代表这个我有一个这样的界面
public interface Regenerative {
void regenerates();
}
所以一个再生的生物是
public class SomeMonster() extends BaseCreature implements Regeneative{
//Code
private int hitPoints;
public void regenerates(){
hitPoints = hitPoints + regenerateValue;
}
}
我面临的问题是,并非所有生物都能再生相同数量的生命值,因此我必须将其数量(regenerateValue)放置在某个地方。 由于我无法将其放置在界面上(因为我不希望所有生物的数量都相同),所以我考虑在生物类中添加新属性
public class SomeMonster() extends BaseCreature implements Regeneative{
//Code
private int regenerateValue;
public void regenerates(){
hitPoints = hitPoints + regenerateValue;
}
}
但是我不喜欢这种方式(为什么不再生的生物的regenerateValue应该为0?)。 我认为它给了类不必要的属性,因此设计很糟糕。 您认为此案例的最佳方法是什么?
我面临的问题是,并非所有生物都能再生相同数量的生命值,因此我必须将其数量(regenerateValue)放置在某个地方。
为什么它必须在任何地方都是一个领域 ? 接口的某些实现可能会对每个实例使用不同的值。 其他人可能使用恒定值。
这是实现细节 ,因此不适用于该接口。 当然,您可以将其放入实现该接口的抽象超类中。
知道界面的代码几乎肯定不应该知道或关心生物再生多少的细节-例如,它们是根据魔术而不是仅仅根据生命值再生的,或者再生的水平取决于其他功能他们的状态。 来电者不在乎。
我会将其添加到abstract
BaseCreature中,不必太担心它。 您的BaseCreature最终可能会具有许多有效“关闭”的属性,但替代方法是创建一个复杂的继承树。 由于Java不支持多重继承,因此这会挫败您抽象所有可能想要的组合的能力。
如果所有怪物都已重新生成,但其中一些具有0的重新生成值(与未重新生成相同),该怎么办?
因此,您不需要下面的代码:
public class SomeMonster() extends BaseCreature {
//Code
protected int regenerateValue; //protected, so that subclasses can override the value
public void regenerates(){
hitPoints = hitPoints + regenerateValue;
}
}
regenerateValue以0开头,因此您必须重写要实际重新生成的子类中的值
编辑删除了“工具再生”
我认为您的设计可能还可以,因为您只需要在实现Regenerative接口的类中包括regenerateValue即可。 因此,无需包含regenerateValue。
否则,您可以查看更偏重于继承而非继承的更复杂的设计模式。 这样,您就可以适应在游戏过程中向怪物动态添加再生能力以及其他“能力”的可能性,而不必在每次需要更改怪物行为时都重新编译游戏。
我使用的解决方案可能有点过头了,但这可以进行很多扩展(再生,毒害,保护...)
我使用接口“ CreatureProperties”来定义一个整数值和一个id,并且可以在每个回合上对怪物执行操作。 您可以将这些属性子类化以执行给定的属性
abstract class CreatureProperties {
protected String id = "";
protectd int propertyValue = 0;
public void actOn(BaseMonster);
// plus setter and getter
}
public RegenerationProperty implements CreatureProperties {
final public REGENERATION_ID = "Regeneration";
int regenerationValue = 0;
public RegenerationProperty(int value){
id = REGENERATION_ID;
propertyValue= value;
}
public void actOn(BaseMonster monster){
monster.setHitPoint(monster.getHitPoints()+propertyValue);
}
}
in the BaseMonster class, you manage a set of MonsterProperty, initially empty.
class BaseMonster {
protected List<CreatureProperties> properties =
new ArrayList<CreatureProperties>();
// plus management of propeties : add remove, iterator...
public void update(){
// perform all properties-linked update to monster
foreach (CreatureProperty property : properties){
property.actOn(this);
}
}
}
在SomeMonster的子类中,只需在实例化过程中添加此怪物类型的属性集即可。
class SomeMonster extends BaseMonster {
public SomeMonster(){
properties.add(new RegenerationProperty(5)); // presto : monster regenerate
}
}
在某些情况下,我会使用Id,但该属性不会在每个刻度上都被使用(例如,更新中没有任何内容),而是例如减少伤害(id =“ LightningReduction”)或修改现有属性列表(删除所有再生属性并添加相同值的PoisonProperty ...)。
您可以在接口中添加一个方法,如getRegnerationValue(),以确保所有具有该接口的生物都具有此方法来保存值或公式(如果您要使用此方法)。
您应该问自己的问题是:如果一个生物应该再生,您怎么知道? 它将实现不同的(或扩展的)基类吗? 一种实现再生的?
如果答案是您将扩展基类(扩展到BaseRegeneratingCreature之类的东西),并且所有正在再生的生物都将扩展该类,那么这就是您的答案:BaseRegeneratingCreature应该实现该接口,并具有再生所需的所有属性。
所有非再生生物都应直接扩展BaseCreature(或另一个扩展类),并且不需要再生相关属性。
然后,您的基类可以具有以下方法:
OnStartOfTurn();
它会在BaseRegeneratingCreature中调用regenerates()(然后可能调用super()),然后在BaseCreature中执行其他操作或调用其他方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.