Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design Pattern to Avoid Abstract Static Methods (or Overriding a Static Method)

I know that static methods can't be abstracted nor can they be overridden, only hidden (and in which case late bindings don't happen). With regard to this, I am struggling with a logical way to express the following relationship:

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; }
}

In this contrived example, max power is an attribute that I expect every spell to know (and every subclass of Spell has an individual max power that applies to all instances of itself). In other SO threads, the proposed solution to this impossible situation is to make getMaxPower() an instance method. However, I don't think this makes sense because power is an implementation detail that is useful to know before instantiation (eg. Constructing an array of spell instances from power 1 to the max power of that spell).

A solution that I see is creating a factory for each spell (or a more generic one for all spells), which has an instance method getMaxPower() that knows the max power attribute of the spell which it instantiates. However, this also doesn't seem optimal to me because:

  1. It makes more sense for each spell to know its own properties
  2. This makes the subclass of Spell oblivious to an implementation detail (namely, its constructor can't check whether a provided power exceeds its max power)

Is the factory pattern the correct approach? If so, what would be the logical justification to it? If not, is there a pattern that more appropriately fits this problem?

like image 528
Bailey Parker Avatar asked Oct 02 '22 00:10

Bailey Parker


1 Answers

Disconnect generating spells from spell would be my first thought.

Have a class that described a spell family with a power range and then use that to create a collection of spells in the range, passing power etc through the constructor.

You could then think about some sort of data file save you a lot of hard coding.

like image 129
Tony Hopkinson Avatar answered Oct 13 '22 00:10

Tony Hopkinson