在Java中选择没有switch语句的子类

时间:2016-06-10 18:59:39

标签: java inheritance subclass

我有一个名为Enemy的基类和各种类型Enemy的子类,如BigEnemy,LazerEnemy,AvoidingEnemy等。

我有一个阵型,其目的是创建敌人的专门编队,例如线,网格,金字塔。

我希望形成能够将我想要创建的敌人子类作为参数。

Formation f = new Formation("LazerEnemy","triangle", 4); // makes a triangle formation of lazer enmies
Formation f = new Formation("BigEnemy","line", 10); // makes a line of big enemies

目前我要做的事情就像传递一个名为enemyType的字符串(或者它可能只是一个整数并做切换语句),但由于我有这么多的敌人类型,我想知道是否有更简洁的方法来通过我想要实例化的对象的类型,不需要使用switch语句。

也许这与Factory和this问题有关,但我不太明白。

由于

5 个答案:

答案 0 :(得分:4)

如果我理解正确,编队构造函数必须能够创建给定类型的敌人的多个实例。你不应该把敌人的类型作为一个字符串或一个类来传递,而应该让一个方式来创建敌人,即工厂供应商的敌人:

public clas Formation<E extends Enemy> {

    // we'll store them in a list
    private List<T> enemies;

    public Formation(Supplier<E> enemySupplier, int count) {
        enemies = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            enemies.add(enemySupplier.get());
        }
    }
}

如果LazerEnemy有一个无参数构造函数,你可以用这种方式创建一个LazerEnemy的形成:

Formation<LazerEnemy> f = new Formation<>(LazerEnemy::new, 10);

假设LazerEnemy构造函数需要lazer的强度,你可以使用

int strenth = 5;
Formation<LazerEnemy> f = new Formation<>(() -> new LazerEnemy(strength), 10);

因此,简而言之,让呼叫者决定并指定必须如何创建阵型中的敌人,而不是强迫阵型知道如何制造所有类型的敌人。

答案 1 :(得分:2)

您可以将类型作为参数传递给方法。

Formation f = new Formation(LazerEnemy.class, Shape.LINE, 4)

public formation(Class<? extends Enemy> enemyType, Shape shape, int num) {
    Enemy enemy1 = enemyType.newInstance(); 
    ...
}

您需要try

答案 2 :(得分:1)

有很多方法可以解决这个问题。其中一个是使用Dependency Inversion principle。即new Formation()构造函数的调用者也可以创建敌人:

Formation f1 = new Formation(new LazerEnemy(), "triangle", 4);
Formation f2 = new Formation(new BigEnemy(), "line", 10);

如果这些敌人有长构造函数,那么你可以使用依赖注入框架。 <{3}} 相对易于设置。

答案 3 :(得分:0)

你应该通过创建敌人Factory界面,然后为所有敌人类型创建EnemyFactories的特定实例来解决。然后像

一样使用它
Formation f = new Formation(LazerEnemyFactory,FormationShape, 4);

答案 4 :(得分:-1)

我可能会选择工厂方法。

Class A

Class B extends A

Class C extends A

public static A factory(string)
  if(string.equal("b")) return new B
  if(string.equal("c")) return new C

这个伪代码可能在边缘有点粗糙,但它应该得到重点。