我有以下课程:
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和Task之间的关联注入工厂的最优雅方法是什么? 考虑到有近100种任务类型,这些类型可能会经常发生变化。
- 进一步说明: 我可以在TaskFactory类中使用smth:
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 :(得分:2)
我建议采用以下方法:
定义一个以@ImplementsTask
为参数的自定义注释TaskType
,以便您可以像这样编写实现类:
@Component
@ImplementsTask(TaskType.VERIFY_X_TASK)
public class VerifyXTask implements Task {
...
(或者您可以对@Component
进行元注释,以避免在所有类中使用它。)
将所有已识别的Task
个对象注入您的工厂:
@Autowired
private Set<Task> scannedTasks;
在工厂的@PostConstruct
方法中,迭代scannedTasks
中的每个元素,读取注释值并添加Map
条目(到{{1} }}, 当然)。您需要决定如何处理给定EnumMap
的重复实现。
这将需要在出厂设置中进行一些反射工作,但这意味着您只需使用适当的值注释TaskType
实现,并在没有任何额外工作的情况下扫描它。
答案 1 :(得分:0)
我遇到了类似的问题要解决,我真正要做的是,这可能会有所帮助。
定义任务枚举之类。
public enum Tasks {
Task1(SubTasks.values());
Tasks(PagesEnumI[] pages) {
this.pages = pages;
}
PagesEnumI[] pages;
// define setter and getter
}
定义的子任务,如
public interface PagesEnumI {
String getName();
String getUrl();
}
public enum SubTasks implements PagesEnumI {
Home("home_url");
SubTasks(String url) {
this.url = url;
}
private String url;
@Override
public String getUrl() {
return url;
}
@Override
public String getName() {
return this.name();
}
}
每个子任务枚举调用的定义服务,如
public interface PageI {
void process();
Sites getTaskName();
PagesEnumI getSubTaskName();
}
@Component
public class Home implements PageI {
// function per SubTask to process
@Override
public void process() {}
// to get the information about Main Task
@Override
public Tasks getTaskName() {
return Tasks.Task1;
}
// to get the information about Sub Task
@Override
public PagesEnumI getSubTaskName() {
return Task1.Home;
}
}
定义一个工厂,例如...
@Component
public class PageFactory {
Set<PageI> pages;
// HashMap for keeping objects into
private static HashMap<String, PageI> pagesFactory = new HashMap<>();
@Autowired
public void setPages(Set<PageI> pages) {
this.pages = pages;
}
// construct key by
private static String constructKey(Tasks taks, PagesEnumI page) {
return task.name() + "__" + page.getName();
}
// PostConstruct means after construct class object this method should get run
// iterating over all pages and storing into Map
@PostConstruct
private void postConstruct() {
for (PageI pageI : pages) {
pagesFactory.put(constructKey(pageI.getTaskName(), pageI.getSubTaskName()), pageI);
}
}
// getting object from factory
public PageI getPageObject(Tasks task, PagesEnumI page) {
return pagesFactory.get(constructKey(task, page));
}
}
到目前为止,我们已经注册了枚举(Tasks和SunTasks)及其服务(带有Tasks和SubTasks的getter),现在定义了一个工厂来调用服务process
方法。
@SpringBootApplication
public class Application implements CommandLineRunner {
PageFactory factory;
@Autowired
public void setFactory(PageFactory factory) {
this.factory = factory;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) throws Exception {
// for each task we might have different sub task
Arrays.stream(Tasks.values()).forEach(
task -> {
// for each and subtask of a task need to perform process
for (PagesEnumI page : task.getPages()) {
PageI pageI = factory.getPageObject(task, page);
pageI.process();
}
}
);
}
}
这不是完全相似的问题,解决它的方法可能相似。因此,我认为将其放在此处可能会有所帮助。请不要输入名称,而只是试图理解概念。如果有人有更多意见,请分享。