0

I am trying to create a Kit system, let me explain. So players are able to redeem kits(rewards). I created the class Kit as an abstract class and several other subclasses, such as WaterKit, FireKit, EarthKit, etc...

My goal is that when a player types or does a specific action if will trigger a giveKit() method. This method will create an object, corresponding the kit they selected. So lets say they decided to redeem the water kit, then it will run the giveKit() and create a WaterKit object.

The way I was thinking to accomplish this was to create a HashMap with a key of a String (the kit name) and the value would be its respective kit object, for example WaterKit. The only problem with is that I don't want to instantiate the Kit objects when added to the HashMap, because the Kit objects take parameters regarding Player information, which I can't provide at the moment I load the HashMap. Every kit parameters change depending on the player that triggered the giveKit(), that is why I can't instantiate the Kit object when added to the HashMap. The HashMap is meant to run as a reference on what object to create, so it would kind of be like this:

// Player triggers giveKit(), they would specify which kit they want (in a String)
// map.get(playerResponse)  <--- that would return a Kit object and then I need to instantiate that object

So my question is how would you guys approach this issue? I am a bit confused as to how to solve it.

ntalbs
  • 28,700
  • 8
  • 66
  • 83
Pablo
  • 91
  • 2
  • 6
  • 3
    more code and less blahblah pls! – injecteer Jul 28 '16 at 16:34
  • Quick question before I answer. Is the logic for creating a kit the same across all kit types? Meaning, is the only difference the constructor for the class type? – Zircon Jul 28 '16 at 16:36

4 Answers4

0

I think you are looking for the Factory Design Pattern.

public class KitFactory {
    public static Kit giveKit(KitType type) {

        Kit kit = null;

        switch (type) {
            case EARTH:
                kit = new EarthKit();
                break;

            case FIRE:
                kit = new FireKit();
                break;

            case WATER:
                kit = new WaterKit();
                break;

            default:
                // throw some exception
                break;
        }

        return kit;
    }
}
κροκς
  • 592
  • 5
  • 18
  • I was thinking of doing this from the start, which would have made it so much easier. However, the issue is that I may have several kits, more than 40. I was trying to avoid creating a switch and case with 30 cases – Pablo Jul 28 '16 at 18:22
0

There are a few ways to go about this. The one which matches your request closest (but is probably not the best way to go about it) is to use reflection (see Instantiate a class by name in java).

However a safer way would be to rearrange your code somewhat so that you have one super Kit class and get rid of all the inheriting classes. That way you can simply pass all the parameters to the giveKit() function (including the kit type, as a string) and create a new Kit object for each instance. Simply don't use fields that aren't required for each fire / water kit etc.

Community
  • 1
  • 1
Drgabble
  • 618
  • 5
  • 17
0

Sounds like you need some variation on the factory pattern. In very general terms a factory is anything that takes some parameters or state as input and returns you a new object.

For example:

class PlayerKitFactory {
    EnumMap<KitType, KitFactory> kitTypes = new EnumMap<>(KitType.class);

    public PlayerKitFactory() {
        kitTypes.put(KitType.WATER_KIT, WaterKit::new); // requires that WaterKit has a constructor that accepts the PlayerInfo.
    }

    Kit getKit(PlayerInformation playerInfo, KitType kitType) {
        return kitType.get(kitType).createKit(playerInfo);
    }
}

KitFactory is just a functional interface that can be implemented by a lambda expression such as WaterKit::new or the equivalent (PlayerInfo playerInfo) -> new WaterKit(playerInfo).

interface KitFactory {
    Kit getKit(PlayerInformation playerInfo);
}

KitType is an enum listing the possible types of kit.

Sam
  • 8,330
  • 2
  • 26
  • 51
0

I would use the getters and setters in a function for instance, say I have my class

class SampleKit {

    private LinkedList<Object> kitItems;
    private String playerData;

    public SampleKit(Object... kits){

        kitItems = new LinkedList<Object>();
        for(Object obj: kits){
            kitItems.add(obj);
        }
        playerData = null;
    }
    public String getPlayerData(){
        return playerData;
    }
    public void setPlayerData(String playerData){
        this.playerData = playerData;
    }
}

the playerData will just remain null until you use it, and whenever you call giveKit() just do something like this

public void giveKit(){
    SampleKit s = HashMap.get("fireKit");
    s.setPlayerData(playerData);
    myKits.add(s);
}
Funny Geeks
  • 483
  • 5
  • 12
  • I like this approach a lot. However, if I do this, the object would be instantiated only once for every kit. Would that be okay? – Pablo Jul 28 '16 at 18:26