Java 设计模式以避免抽象静态方法(或重写静态方法)
我知道静态方法不能被重写,也不能被重写。关于这一点,我正在努力用一种合乎逻辑的方式来表达以下关系:Java 设计模式以避免抽象静态方法(或重写静态方法),java,oop,design-patterns,static-methods,abstract,Java,Oop,Design Patterns,Static Methods,Abstract,我知道静态方法不能被重写,也不能被重写。关于这一点,我正在努力用一种合乎逻辑的方式来表达以下关系: public abstract class Spell { protected int power; public Spell(int power) { this.power = power; } public int getPower() { return power; } // I know this is impossible,
public abstract class Spell {
protected int power;
public Spell(int power) {
this.power = power;
}
public int getPower() { return power; }
// I know this is impossible, but please bare with me
public abstract static int getMaxPower();
}
public class AttackSpell extends Spell {
public AttackSpell(int power) {
super(power);
}
public static int getMaxPower() { return 50; }
}
public class HealSpell extends Spell {
public HealSpell(int power) {
super(power);
}
public static int getMaxPower() { return 30; }
}
在这个精心设计的例子中,max power是一个我希望每个法术都知道的属性(并且spell
的每个子类都有一个单独的max power,它适用于自身的所有实例)。在其他SO线程中,针对这种不可能的情况提出的解决方案是将getMaxPower()
作为实例方法。然而,我认为这没有意义,因为power是一个实现细节,在实例化之前知道它很有用(例如,构建一个从power 1到该咒语最大power的咒语实例数组)
我看到的一个解决方案是为每个法术创建一个工厂(或者为所有法术创建一个更通用的工厂),它有一个实例方法getMaxPower()
,该方法知道它实例化的法术的最大功率属性。但是,这对我来说也不是最佳选择,因为:
工厂模式是正确的方法吗?如果是的话,它的逻辑依据是什么?如果没有,是否有一种模式更适合这个问题?我的第一个想法是断开生成咒语和咒语的连接 有一个类,描述了一个法术家族的异能范围,然后用它来创建一个范围内的法术集合,通过构造函数传递异能等
然后,您可以考虑使用某种类型的数据文件来节省大量的硬编码。由于您只能覆盖非静态函数,因此我认为只有一种方法可以做到这一点:您必须以某种方式将信息附加到
类
对象
但这不是设计模式,我知道
您最好用信息注释类并使用反射。因为注释可以被继承,所以这正是您想要的行为。请参见拼写中的main
,了解如何使用它的示例
注释类型的定义:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface SpellInfo {
int maxPower();
}
注意:Integer.MIN\u VALUE
是此处“未定义”的值
一个简单的方法是将
getMaxPower()
转换为工厂方法。在幕后,它实例化自身的一个实例,缓存它并查询该实例。有趣。这样的注释被认为是最佳实践吗?
@SpellInfo(maxPower = Integer.MIN_VALUE)
public class Spell {
protected int power;
public Spell(int power) {
this.power = power;
}
public int getPower() { return power; }
public static int getMaxPower(Class<? extends Spell> c) {
return c.getAnnotation(SpellInfo.class).maxPower();
}
public final int getMaxPower() {
return getMaxPower(this.getClass());
}
// test it
public static void main(String[] args) {
System.out.println("Spell.getMaxPower(Spell.class)="+
Spell.getMaxPower(Spell.class));
System.out.println("Spell.getMaxPower(AbstractSpellType.class)="+
Spell.getMaxPower(AbstractSpellType.class));
System.out.println("Spell.getMaxPower(HealingSpell.class)="+
Spell.getMaxPower(HealingSpell.class));
System.out.println("Spell.getMaxPower(AttackSpell.class)="+
Spell.getMaxPower(AttackSpell.class));
Spell spell = new AttackSpell(3);
System.out.println("((Spell) new AttackSpell(3)).getMaxPower()=" +
spell.getMaxPower());
spell = new HealingSpell(4);
System.out.println("((Spell) new HealingSpell(4)).getMaxPower()=" +
spell.getMaxPower());
}
}
public abstract class AbstractSpellType extends Spell {
public AbstractSpellType(int power) {
super(power);
}
}
@SpellInfo(maxPower = 30)
public class HealingSpell extends Spell {
public HealingSpell(int power) {
super(power);
}
}
@SpellInfo(maxPower = 50)
public class AttackSpell extends Spell {
public AttackSpell(int power) {
super(power);
}
}