Ok, I understand better now what you are after I think. I have found myself in a similar situation where it felt like I was duplicating code. It was a similar case where I have a library of things and every time I add a new subtype, I also have to remember to create a new entry for the new thing.
I have issues with what you have because reflection is slow, using String keys makes things a pain, and you are relying on naming conventions. If you use an Enum, you are right back to where you started where you have to specify every item in the enum class. I also don’t like reflection because it usually means more runtime errors that may have been compiler errors.
Having said all of that…one thing you could do to make it more palatable is to do all of your reflecting once up front, so you didn’t need to do it every time you wanted to equip someone with something new. You could use the Reflections library to get a listing of all of the classes that subclass Weapon. You could then put a new instance of each class it into a Map where the key is the name. This would give you a library of “prototypes” that you could pull from. If you had an abstract getPrototype() method in the Weapon class each subclass could have code that would create a new “blank weapon” of that type. You could also override clone().
That all being said, I still don’t like the approach and wouldn’t use it. Another problem is what happens when you would like to pass in parameters at creation time? I knocked up in the browser window of how something like this might look…I am sure there are some mistakes. The code below could all be in a WeaponLibrary class. The only thing I really like about this is that you can create a new Weapon subclass and it will be made available here without having to also remember to add fields to enum classes or to if-then statements.
I just did this as an exercise, I don’t think I would use code like this…
// A map that holds a list of weapon prototypes, that will be indexed by their name.
private Map<String,Weapon> weaponPrototypes;
public void init() {
weaponPrototypes = new HashMap<String,Weapon>();
// Assume I have a list of all subclasses from the Reflections library.....I have no idea how it works.
List<ClassSpec> weaponsClasses = Reflections.getSubClassesOf(Weapon.class);
// I am guessing that the Reflections library allows you to get an object that has information about the class.
for (ClassSpec classSpec : weaponsClasses) {
// Use the prefix to access the name. (7 letters in Weapon1)
// So WarriorWeapon1 should become Warrior
String weaponPrefix = classSpec.getName(0,classSpec.getName().length-7);
// Add a new instance of the weapon class to the map.
prototypes.put(weaponPrefix,classSpec.getClass().newInstance();
}
// Returns a new copy of the prototype weapon based on its name.
public Weapon getWeapon(String weapon) {
return prototypes.get(weapon).getPrototype();
}