Example
I have an "Enemy" class
, and 5 types of enemy subclasses
.
These enemies will be spawn often, so I want to use an object pool.
However, this means I can no longer use an object pool for Enemies, now I have to use an object pool for each enemy subclass, so now, I have to make 5 object pools, and that's an arbitrary number that could just as easily be 25.
eg.
// Each with their own implementations of Enemy's "attack" or similar method
class Dragon extends Enemy { ... }
class Ogre extends Enemy { ... }
ObjectPool<Ogre> ogrePool;
ObjectPool<Dragon> dragonPool;
// etc ...
It seems a bit weird.
So what can I do? If I take out the subclasses, I can either put all the functionallity of every subclass into the base class, and keep an id of the type of class this base class represents, calling the appropriate functions accordingly... But this leaves a bloated hard to maintain class that requires a lot of modification everytime I add or remove a subclass behaviour.
eg:
class Enemy {
enum EnemyType {OGRE, DRAGON, ETC;}
EnemyType enemyType;
public Enemy(EnemyType type) { this.enemyType = type; }
public void attack() {
switch(enemyType) {
case Ogre:
//Do ogre attack
break;
// etc...
}
// ...
}
// Now I can instantiate things from 1 object pool
Alternately I could try and use composition. I could have enemy contain components of other classes that govern behaviour. For example, I could have something like an "WeaponBehaviour" and "ArmourBehaviour". Then, the type of weapon behaviour, armour behavour, etc, would differentiate the different subclasses. However, every time i obtain an inatnace of my enemy class, I would have to instantiate each behaviour, and would end up likely needing an object pool for each behaviour.
eg:
class Enemy {
WeaponComponent weaponComponent;
ArmourComponent armourComponent;
public Enemy() {}
public void init(WeaponComponent weapon, ArmourComponent armour) {
weaponComponent = weapon;
armourComponent = armour;
}
public void attack() {
weaponComponent.attack();
}
// ...
}
// And then instantiate things like so:
ObjectPool<Enemy> enemyObjectPool;
Enemy enemy = enemyObjectPool.obtain();
enemy.initialize(new OgreWeapon(), new OgreArmour());
// or alternately have an object pool for OgreWeapons and OgreArmour
None of the solutions I can think of seem like they are ideal, and I was wondering what a good way to organize this was.