vendredi 9 septembre 2022

What design pattern to use when you need derived class field values but you only have base class field variables?

Consider the following code:

abstract class Player{
    abstract Stats getStats();
}

abstract class RangedPlayer:Player{
    RangedStats rangedStats;
    override Stats getStats() {return rangedStats;}
}

abstract class MeleePlayer:Player{
    MeleeStats meleeStats;
    override Stats getStats() {return meleeStats;}
}

class Stats{
    int maxHealth;
}

class RangedStats:Stats{
    int maxAmmo;
}

class MeleeStats:Stats{
    int meleeComboLength;
}

abstract class ThingPlayersCando{
    Player player;
    abstract void doThing(); 
}
class ThingMeleePlayersCando: ThingPlayersCando{
    abstract void doThing(){
        //getMeleeComboLength from base player class?
    }
}
class ThingRangedPlayersCando: ThingPlayersCando{
    abstract void doThing(){
        //maxAmmo from base player class?
    }
}

Here I made ThingMeleePlayersCanDo and ThingRangedPlayersCando both inherit from ThingPlayersCando because sometimes accessing the Player class is useful for both. But sometimes I may also want to access only things available to Melee or RangedStats.

The shared interface/abstract class is necessary because I want to call doThing() without needing to care about the type.

The getStats() in player class is necessary because somethings only need to know stuff shared by all players(e.g maxHP)

I thought of the following fixes:

  1. Just cast stats to appropriate type.
  2. Do away with Ranged and Melee Stats and put all fields in single Stats class. Simplest and it's not like having more data fields is going to hurt.
  3. Player stats is a dictionary/hashmap. Ugly.
  4. Pass in RangedStats/RangedPlayer in ThingRangedPlayersCanDo constructor. Same for melee.

Is there a design pattern that can solve this issue in a better way?

Aucun commentaire:

Enregistrer un commentaire