简体   繁体   中英

Is there a better/cleaner way to conditionally create a type than using instanceof? [Java]

Suppose I have:

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>(); // /!\

}

The problem is MobileSuitCollection is an Interface, so I can't instantiate it. For example, I could do:

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

etc. However, to manipulate temporaryCollection , I need it to be of the same type as the one passed via parameter to my Class. So I thought about doing this:

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

I realize that is awful however. Is there a better way to do this? Would it be possible to keep a reference to the class used by the initial type and then instantiate the temporaryCollection with that?

The code that you place in the if-clause can be placed in a 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
}

and then let MobileSuitCollection have a method:

void visit(MobileSuitCollectionVisitor visitor);

And in each implementation of MobileSuitCollection simply have

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

A quick and dirty way to do it would be to clone the original collection, then manipulate it as needed. A better way might be to add a newInstance() method to the interface, or pass in a factory to FightingZone .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM