2015-02-13 5 views
3

У меня есть интерфейс «Родительский» и несколько классов (скажем, Abc.java, Def.java и Xyz.java), реализующие интерфейс. Теперь я хочу сделать что-то вроде этого:Определение реализации класса на основе некоторых условий в Java

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; 
} 

В основном я передаю имя класса, который будет экземпляр в качестве параметра метода. Каков наилучший способ сделать это? Должен ли я использовать рефлексию для этого? Его не только 3 класса, может быть намного больше. Поэтому я не хочу писать if/else.

Спасибо.

+1

Вы уверены, что ** все ** классы реализации имеют конструктор по умолчанию (без параметров) (неявный или явный)? –

+0

Если да, то комментарий @ PM77-1, я бы предложил отражение в этом сообщении: http://stackoverflow.com/questions/14680954/instantiate-java-classes-which-implements-specific-interface-using-reflection – ThePerson

+0

Вы уже делаете это так, как я предлагаю. –

ответ

0

Вы можете выбрать конструктор, который будет использоваться на основе имени класса, для которого вы пытаетесь создать объект. Что-то вроде:

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

0

Если вы знаете полное имя класса, вы можете использовать Reflection API, как это:

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

А что, если у меня нет полного имени класса? Что я могу сделать тогда? – drunkenfist

1

Вы можете использовать перечисление реализовать шаблон стратегии следующим образом:

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(); 
} 
3

Один из способов - определить метод как общий, с параметром типа, расширяющим Parent, а затем создать экземпляр путем отражения:

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

Вы можете использовать метод следующим образом:

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); 

Однако это предполагает, что все подклассы Parent не имеют аргументов конструктора (либо они определяют конструктор без аргументов или они не определить любой конструктор, следовательно, иметь конструктор по умолчанию).

Смежные вопросы