2

我有以下课程:

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 类中做这样的事情:

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 对象中注入任何属性。

4

2 回答 2

3

我建议采用以下方法:

  1. 定义一个@ImplementsTask以 aTaskType作为参数的自定义注解,以便您可以像这样编写实现类:

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

    (或者您可以进行元注释@Component以避免在所有类上都使用它。)

  2. 将所有已识别的Task对象注入您的工厂:

    @Autowired
    private Set<Task> scannedTasks;
    
  3. @PostConstruct工厂的方法中,遍历 中的每个元素scannedTasks,读取注释值并添加一个Map条目(EnumMap当然是添加到 中)。您需要决定如何处理给定TaskType.

这将需要在工厂设置中进行一些反射工作,但这意味着您只需使用Task适当的值注释实现并对其进行扫描,而无需实现者进行任何额外的工作。

于 2013-10-03T09:28:22.450 回答
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();
                }
            }
        );
    }
}

这不是完全相似的问题,解决它的方法可能相似。所以我认为把它放在这里可能会有所帮助。请不要通过命名,只是试图理解概念。如果有人有更多的投入,请分享。

于 2020-03-21T08:22:47.250 回答