2013-06-02 2 views
0

Я хочу создать шаблон фабрики в java с дженериками. Мой код:Создатель объектов фабрики с generics

Интерфейс:

public abstract class Factory<T> { 
    public abstract T create(); 
} 

FactoryA класс:

public class FactoryA extends Factory<FactoryA> { 

    public FactoryA() { 

    } 

    public FactoryA create() { 
     return new FactoryA(); 
    } 

} 

FactoryB класс:

public class FactoryB extends Factory<FactoryB> { 

    public FactoryB() { 

    } 

    public FactoryB create() { 
     return new FactoryB(); 
    } 

} 

Основной класс:

public class FactoryCreator { 

    public static <T> T createFactory() { 
     Factory<T> t = ?; // is that right way? 
     return t.create(); 
    } 

    public static void main(String[] args) { 
     FactoryA factoryA = FactoryCreator.createFactory(); 
     FactoryB factoryB = FactoryCreator.createFactory(); 
    } 
} 

Вопрос, что Завод t = должен быть равен или есть ли другой способ?

+1

Нет никакого способа сделать это, как вы надеетесь. Вам нужно будет закончить выполнение FactoryA factoryA = FactoryA.create() '. –

+0

@ louis-wasserman, Это не заводская модель. – phpnuker

+0

Почему вы хотите создать класс, служащий фабрикой такого рода? Может быть, вы хотите, чтобы класс FactoryA служил фабрикой класса A? – nakosspy

ответ

0

Нечто подобное может работать:

public static <T extends Factory> T createFactory(Class<T> clazz) { 
    try { 
     t = clazz.newInstance(); 
     return t.create(); 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     return null; 
    } 
} 
... 
FactoryA factoryA = FactoryCreator.createFactory(FactoryA.class); 

в качестве альтернативы, без параметров. Но тогда вам нужны два метода.

public static FactoryA createFactoryA() { 
    return new FactoryA().create(); 
} 
... 
FactoryA factoryA = FactoryCreator.createFactoryA(); 

Поскольку Обобщенные типы удаляются во время выполнения вы должны поставить параметр Class, так что среда выполнения знает, какой класс вы говорите.

+1

Попробуйте в [ideone] (http://ideone.com/) и решите свое любопытство. –

+0

Пробовал это в Eclipse и компилирует хотя бы;) Интересная ссылка, хотя, спасибо. – koljaTM

+0

@koljaTM, я знаю это, но я не хочу указывать параметр типа класса в методе createFactory, потому что ** ** делает это. – phpnuker

1

Не совсем уверен, чего вы пытаетесь достичь, но это может помочь;

public interface Factory<T> 
{ 
    public T create(String type); 
    public T create(String type, Object arg); 
    public T create(String type, Object[] args); 
} 

А затем укомплектовывайте класс таким интерфейсом фабрики, как это;

public class TemplateFactory<T> implements Factory { 

    @Override 
    public T create(String type) throws IllegalArgumentException 
    { 
     return create(type, null); 
    } 

    @Override 
    public T create(String type, Object arg) throws IllegalArgumentException 
    { 
     // Convert to array of 1 element 
     Object[] arguments = new Object[1]; 
     arguments[0] = arg; 
     return create(type, arguments); 
    } 

    @Override 
    public T create(String type, Object[] args) throws IllegalArgumentException 
    { 
     // Create array for all the parameters 
     Class<?> params[] = (args != null) ? new Class<?>[args.length] : new Class<?>[0]; 
     if(args != null) 
     { 
      // Adding the types of the arguments 
      for(int i = 0; i < args.length; ++i) 
       params[i] = (args[i] != null) ? args[i].getClass() : null; 
     } 

     try 
     { 
      // Create a class variable 
      Class classLoader = Class.forName(type); 
      // Find the right constructor 
      Constructor co; 
      if(params.length > 0) 
       co = classLoader.getConstructor(params); 
      else 
       co = classLoader.getConstructor(); 
      // Instantiate the class with the given arguments 
      T newObject = (T)co.newInstance(args); 
      return newObject; 
     } 
     catch(Exception e) 
     { 
      throw new IllegalArgumentException(e.toString()); 
     } 
    } 
} 

И затем использовать его как это (используя некоторые мнимые стратегии-классы в качестве примера):

TemplateFactory<StrategyInterface> factory; 
factory = new TemplateFactory<>(); 

factory.create("packageName.StrategyA"); 
factory.create("packageName.StrategyB"); 
factory.create("packageName.StrategyC"); 

Классы стратегии (А, В и С) будет осуществлять StrategyInterface-класс в этом пример.

+0

Это сосать, что это более или менее единственный способ сделать это (очевидно, способ создания объекта класса KOLJTM также будет работать, хотя это означает, что связь сильнее). Нет ли новых трюков в Java8, которые делают это более ... чистым? – demaniak

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