Spring-基于枚举的动态工厂

问题描述 投票:0回答: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对象中注入任何属性。

java spring enums factory
2个回答
2
投票

我建议采用以下方法:

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

    @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的重复实现。

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

我遇到了类似的问题要解决,我真正要做的是,可能会有帮助。

类似于定义任务枚举。

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

要像每个SubTasks枚举一样调用的定义服务


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,现在定义了一个工厂来调用service 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();
                }
            }
        );
    }
}

这不是完全相似的问题,解决方法可能相似。因此,我认为将其放在此处可能会有所帮助。请不要输入名称,而只是试图理解概念。如果有人有更多意见,请分享。


0
投票

我遇到了类似的问题要解决,我真正要做的是,可能会有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.