简体   繁体   中英

Determining implementing class based on some condition in Java

I'm having an interface "Parent", and multiple classes (say Abc.java, Def.java, and Xyz.java) implementing the interface. Now I want to do something like this:

Parent factoryMethod(String condition){
    Parent p = null;
    if(condition.equals("Abc"))
        p = new Abc();
    else if(condition.equals("Def"))
        p = new Def();
    else if(condition.equals("Xyz"))
        p = new Xyz();
    return p;
}

Basically I'm passing the name of the class to be instantiated as the parameter to the method. What is the best way to be doing this? Should I use reflection for this? Its not just 3 classes, there might be a lot more. So I don't want to write if/else.

Thanks.

One way is to define the method as a generic one, with a type parameter extending Parent , and then create the instance by reflection:

<T extends Parent> T factoryMethod(Class<T> clazz) throws Exception {
    return (T) clazz.newInstance();
}

You can then use the method as follows:

Abc abc = obj.factoryMethod(Abc.class);
Def def = obj.factoryMethod(Def.class);

// The below won't compile if SomeOtherClass does not implement Parent
SomeOtherClass instance = obj.factoryMethod(SomeOtherClass.class); 

However this assumes that all subclasses of Parent have no-argument constructor (either they define a no-argument constructor or they don't define any constructor, hence having a default constructor available).

You could use an enum to implement a strategy pattern like so:

public enum ParentFactory {
    Abc(Abc.class),
    Def(Def.class),
    Xyz(Xyz.class);

    private Class<? extends Parent> childClass;

    private ParentFactory(Class<? extends Parent> childClass) {
        this.childClass = childClass;
    }

    public <T extends List> T getParentInstance() throws InstantiationException, IllegalAccessException {
        return (T) childClass.newInstance();
    }
}


public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    ParentFactory parentFactory = ParentFactory.valueOf("Abc");
    Parent parent = parentFactory.getParentInstance();
}

You can chose the constructor to be used on the basis of the name of the class you are trying to create an object for. Something like:

Class<?> theClass = Class.forName(condition); Constructor<?> theClassConstructor = theClass.getConstructor(); Object object = theClassConstructor.newInstance(new Object[] { args });

If you know the full class name, you could use the Reflection API like this :

try {
    return Class.forName(condition).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
    // do something with exception
}

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