如何基于Enemy子类对象创建新实例?求最优实现方案
如何基于已有Enemy实例创建同类型的独立新实例?
嘿,你的需求其实很明确:要从已选的Enemy实例列表里,生成一批同类型但完全独立的新敌人,避免同种类敌人共享属性对吧?我给你两个可行方案,优先推荐第一个,更稳妥可控。
方案一:让每个Enemy子类实现“自我复制”方法(推荐,类型安全)
这个思路的核心是:把创建同类型新实例的责任交给每个子类自己,这样既能保证类型安全,又能让每个子类灵活控制新实例的初始化逻辑。
首先给抽象父类Enemy定义一个抽象方法,让所有子类必须实现它:
abstract class Enemy { // 示例属性:每个敌人都有的生命值 protected int health; // 抽象方法:要求子类返回自己的新实例 public abstract Enemy createNewInstance(); // 其他通用方法比如攻击、受击等... }
然后每个具体的Enemy子类(比如哥布林、兽人)实现这个方法,返回自己的新对象:
// 哥布林子类 class Goblin extends Enemy { // 哥布林独有的属性:攻击力 private int damage; @Override public Enemy createNewInstance() { // 返回一个全新的Goblin实例 // 如果需要复制原实例的部分属性,可以改成 new Goblin(this.health, this.damage) return new Goblin(); } // 构造方法(根据需求定义) public Goblin() { this.health = 50; this.damage = 10; } } // 兽人子类 class Orc extends Enemy { // 兽人独有的属性:是否穿盔甲 private boolean isArmored; @Override public Enemy createNewInstance() { return new Orc(); } public Orc() { this.health = 100; this.isArmored = true; } }
最后在你的Generator类里,直接调用每个实例的createNewInstance()方法就行:
class Generator { public ArrayList<Enemy> generateEnemies(ArrayList<Enemy> selectedToGenerate) { ArrayList<Enemy> newEnemies = new ArrayList<>(); for (Enemy enemyTemplate : selectedToGenerate) { // 调用模板实例的方法,得到同类型的全新敌人 Enemy newEnemy = enemyTemplate.createNewInstance(); newEnemies.add(newEnemy); } return newEnemies; } }
这个方案的好处:
- 类型安全:编译期就能检查每个子类是否正确实现了方法,不会出现运行时类型错误
- 灵活可控:每个子类可以自己决定新实例的初始化逻辑(比如要不要复制原模板的属性)
- 完全避免属性共享:每个新敌人都是独立的对象,各自拥有自己的属性值
方案二:使用反射创建实例(不推荐,仅作备选)
如果不想给每个子类加方法,也可以用反射来动态获取对象的Class,然后创建新实例。但这个方案有不少缺点,只适合特殊场景。
代码示例:
class Generator { public ArrayList<Enemy> generateEnemies(ArrayList<Enemy> selectedToGenerate) { ArrayList<Enemy> newEnemies = new ArrayList<>(); for (Enemy enemyTemplate : selectedToGenerate) { try { // 获取当前对象的Class,调用无参构造方法创建新实例 Enemy newEnemy = enemyTemplate.getClass().getDeclaredConstructor().newInstance(); newEnemies.add(newEnemy); } catch (Exception e) { // 必须处理一堆异常:找不到构造方法、权限问题等 e.printStackTrace(); } } return newEnemies; } }
这个方案的缺点:
- 需要处理多种异常,代码不够简洁
- 如果子类没有无参构造方法,运行时会直接报错,编译期无法提前发现
- 可读性差,其他开发者看代码时不容易理解你的意图
总结
优先选择方案一,它既符合面向对象的设计原则,又能完美满足你的需求:每个新生成的敌人都是同类型的独立实例,不会和原模板或其他敌人共享属性,而且完全基于你选定的selectedToGenerate列表来生成。
内容的提问来源于stack exchange,提问作者MisterWoam
相关产品推荐
相关产品推荐

