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()
,该方法知道它实例化的法术的最大功率属性。但是,这对我来说也不是最佳选择,因为:

  • 每个法术都知道自己的属性,这更有意义
  • 这使得Spell的子类忽略了实现细节(即,其构造函数无法检查提供的功率是否超过其最大功率)

  • 工厂模式是正确的方法吗?如果是的话,它的逻辑依据是什么?如果没有,是否有一种模式更适合这个问题?

    我的第一个想法是断开生成咒语和咒语的连接

    有一个类,描述了一个法术家族的异能范围,然后用它来创建一个范围内的法术集合,通过构造函数传递异能等


    然后,您可以考虑使用某种类型的数据文件来节省大量的硬编码。

    由于您只能覆盖非静态函数,因此我认为只有一种方法可以做到这一点:您必须以某种方式将信息附加到
    对象

    但这不是设计模式,我知道

    您最好用信息注释类并使用反射。因为注释可以被继承,所以这正是您想要的行为。请参见拼写中的
    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);
        }
    }