替代反射以生成随机子类的对象

时间:2016-05-10 21:42:30

标签: java

我的Java程序有问题。我的程序有一个接口Bonus和九个扩展Bonus的子类。我必须生成一个Bonus的随机实例,我不能使用原型模式,因为每个奖金的数量都是随机的,所以我每次需要时都要创建奖金。

切换语句,如果不是解决方案,因为我有太多的子类,代码将非常冗长和粗糙。

所以我决定使用反射,它对我来说非常好,但我的教授告诉我,反射是一个坏技巧,因为不是类型安全的,每次我更改奖金子类的名称,我必须改变我班GenerateBonus中的代码。

我在互联网上搜索,但没有找到适合我的解决方案。 所以任何人都知道反射的替代方法来生成随机子类的对象吗?

2 个答案:

答案 0 :(得分:3)

你需要两件事:

  1. 如果你想选择一个随机项(在你的情况下是一个子类),必须有一些地方包含有关所有可能项目的信息。
  2. 一种选择子类后如何创建所需实例的方法。
  3. 对于创作,如果你不能使用原型,我会使用Supplier或工厂。以下是供应商的示例:

        ArrayList<Supplier<Bonus>> bonuses = new ArrayList<>();
        bonuses.add(Bonus1::new);
        // ...
        bonuses.add(Bonus9::new);
        int randomNumber = generateRandomNumber(bonuses.size());
        Bonus randomBonus = bonuses.get(randomNumber).get();
    

    对于第一个问题,即获取所有可能奖励的列表,您可以简单地将它们添加到集合中,如上例所示,创建包含所有值的枚举等。

    这是一个枚举示例:

    enum AllBonuses{
        Bonus1(BonusClass1::new),
        // ...
        Bonus9(BonusClass9::new);
    
        private final Supplier<Bonus> bonus;
        AllBonuses(Supplier<Bonus> bonus) { this.bonus = bonus; }
        public Bonus create() { return bonus.get(); }
    }
    
    // Usage:
    int randomNumber = generateRandomNumber(AllBonuses.values().length);
    Bonus randomBonus = AllBonuses.values()[randomNumber].create();
    

    我不会使用反射。除非没有别的办法,否则反思很少是一个好的解决方案。

    更新:如果您出于某种原因无法使用供应商(例如,您没有Java 8),您可以使用旧的工厂模式:

    class Bonus1Factory implements BonusFactory {
        @Override
        public Bonus create() { return new BonusClass1(); }
    }
    // ...
    ArrayList<BonusFactory> bonuses = new ArrayList<>();
    bonuses.add(new Bonus1Factory());
    // ...
    

答案 1 :(得分:1)

使用9个子类我会使用切换语句

int randomSubClass = getRandomNumber();
switch(randomSubClass) {
   case 1:
     return generateRandomFunBonus();
   case 2:
     return generateRandomHardBonus();
   ...
   default:
     throw new Exception(":(");
}

作为打开int的替代方法,您可以拥有enum,每个子类有一个条目和覆盖的create方法。