2013-10-03 3 views
0

У меня есть следующие классы:Весна - Динамическая фабрика, основанная на перечислении

public enum TaskType { 

    VERIFY_X_TASK, COMPUTE_Y_TASK, PROCESS_Z_TASK; 
} 

public interface Task{ 
    void process(); 
} 

@Component 
public class VerifyXTask implements Task{ 
    // Similar classes for the other types of tasks 
    public void process() { 
    } 
} 

@Component 
public class TaskFactory{ 
    private Map<TaskType, Task> tasks; 
    public Task getTask(TaskType type){ 
     return tasks.get(type); // return a singleton with all it's fields injected by the application context 
    } 
} 

class UseTool{ 
    @Autowired 
    private TaskFactory taskFactory; 

    public void run(String taskType){ 
     Task task = taskFactory.getTask(TaskType.valueOf(taskType)); 
     task.process(); 
    } 
} 

Самый элегантный способ инъекционного ассоциации между TaskType и задачи на завод? Учтите, что существует почти 100 типов задач, и они могут изменяться довольно часто.

- Дальнейшие объяснения: я мог бы сделать в TaskFactory класса, как чего-л:

tasks.put(TaskType.VERIFY_X_TASK, new VerifyTask()); 
tasks.put(TaskType.COMPUTE_Y_TASK, new ComputeTask()); 
tasks.put(TaskType.PROCESS_Z_TASK, new ProcessTask()); 

Но это не инъекционные каких-либо свойств в объекте Task.

+0

Не совсем понятно, что вы пытаетесь сделать; почему у вас есть «перечисление», это список операций, а затем нет каких-либо отношений между значениями «enum» и реализующими классами? – chrylis

+0

Вопрос в том, как сопоставить эти отношения. Я мог бы сделать на фабрике smth like tasks.put (VERIFY_X_TASK, новый VerifyTask()); и т. д., но новый оператор не будет вводить зависимостей VerifyTasks. –

ответ

2

Я хотел бы предложить следующий подход:

  1. Определить пользовательский аннотацию @ImplementsTask, который принимает TaskType в качестве параметра, так что вы можете написать класс реализации, как это:

    @Component 
    @ImplementsTask(TaskType.VERIFY_X_TASK) 
    public class VerifyXTask implements Task { 
    ... 
    

    (Или вы можете мета-аннотировать @Component, чтобы избежать необходимости использовать его на всех классах.)

  2. I nject все выявленные Task объектов на ваш завод:

    @Autowired 
    private Set<Task> scannedTasks; 
    
  3. В @PostConstruct методе на заводе-изготовителе, итерация по каждому из элементов в scannedTasks, считывание значения аннотаций и добавление Map записи (к EnumMap, конечно). Вам нужно будет решить, как иметь дело с повторяющимися реализациями для заданного TaskType.

Это потребует немного отражения работы в заводских настройках, но это означает, что вы можете просто аннотировать Task реализации с соответствующим значением и он сканируется без какой-либо дополнительной работы исполнителя.

+0

Очень элегантное решение. Благодарю. –

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