[英]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.