【问题标题】:Is there a better/cleaner way to conditionally create a type than using instanceof? [Java]有没有比使用 instanceof 更好/更干净的方法来有条件地创建类型? [爪哇]
【发布时间】:2010-06-29 21:09:12
【问题描述】:

假设我有:

public class FightingZone<MobileSuitso, Background> {

    private MobileSuitCollection<MobileSuitso> msCollection;
    private BackgroundInfo<Background> bgInfo;

    public FightingZone(MobileSuitCollection<MobileSuitso> newCollection, BackgroundInfo<Background> newInfo) {
        this.msCollection = newCollection;
        this.bgInfo = newInfo;
    }

    ...

        ...// inside a method
        MobileSuitCollection temporaryCollection = new MobileSuitCollection<MobileSuitso>(); // /!\

}

问题是 MobileSuitCollection 是一个接口,所以我无法实例化它。例如,我可以这样做:

MobileSuitCollection temporaryCollection = new GundamMeisterCollection<MobileSuitso>();
MobileSuitCollection temporaryCollection = new InnovatorCollection<MobileSuitso>();
MobileSuitCollection temporaryCollection = new CannonFolderCollection<MobileSuitso>();

等等。但是,要操作temporaryCollection,我需要它与通过参数传递给我的类的类型相同。所以我想这样做:

if (msCollection instanceof GundamMeisterCollection) {
    ...
} else if (msCollection instanceof InnovatorCollection) {
    ...
} ...

我意识到这很糟糕。有一个更好的方法吗?是否可以保留对初始类型使用的类的引用,然后用它实例化temporaryCollection

【问题讨论】:

    标签: java design-patterns oop instanceof


    【解决方案1】:

    您放在 if 子句中的代码可以放在 Visitor 中:

    // Generics skipped for brevity
    interface MobileSuitCollectionVisitor {
       handleCollection(GundamMeisterCollection collection);
       handleCollection(InnovatorCollection collection);
       handleCollection(CannonFolderCollection collection)
    }
    
    class ConcreteVisitor implements MobileSuitCollectionVisitor { 
        // place all of the logic in the implemented methods
    }
    

    然后让MobileSuitCollection有一个方法:

    void visit(MobileSuitCollectionVisitor visitor);
    

    并且在MobileSuitCollection 的每个实现中都只有

    public void visit(MobileSuitCollectionVisitor visitor) {
        visitor.handleCollection(this);
    }
    

    【讨论】:

    • 我正在研究使用反射来获取类名并从那里实例化它。假设这是可能的,它不会使代码更干净吗?还是这仍然是首选方法?
    • 如果要使用反射,请使用类对象而不是类名。像这样:Class&lt;Interface&gt; cl=collection.getClass();Interface inst=cl.newInstance();
    • 反思应该是最后的手段。上述方法是面向对象的方法。
    【解决方案2】:

    一种快速而肮脏的方法是克隆原始集合,然后根据需要对其进行操作。更好的方法可能是将newInstance() 方法添加到接口,或者将工厂传递给FightingZone

    【讨论】:

      猜你喜欢
      • 2021-08-22
      • 2012-01-20
      • 2019-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      相关资源
      最近更新 更多