具有多种实现的Java通用接口

时间:2018-11-13 08:08:48

标签: java generics interface

我有以下情况:

public abstract class BaseTask{...}

public class TaskA extends BaseTask {....}

public class TaskB extends BaseTask {....}

public interface TaskService<T extends BaseTask>{
        void process(T task);
}

@Service @Qualifier("taskServiceA")
public class TaskServiceA<TaskA> implements TaskService<TaskA>{
}

@Service @Qualifier("taskServiceB")
public class TaskServiceB<TaskB> implements TaskService<TaskB>{
}

public class ProcessingService{

        @Autowired @Qualifier("taskServiceA")
        private TaskService<TaskA> taskAService;

        @Autowired @Qualifier("taskServiceB")
        private TaskService<TaskB> taskBService;

        public void process(Order o){
            BaseTask task = o.getTask();
            getTaskService(o).start(task);
        }

        private <T extends BaseTask> TaskService<T> getTaskService(Order o){
            if("atype".equals(o.type)){
              return (TaskService<T>) taskAService;
            } else if("btype".equals(o.type)){
              return (TaskService<T>) taskBService;
            }
        }
}

更新:我对这个问题进行了重新措辞,因为我得到的答案不是我想要的。

我的问题与getTaskService方法有关。

  1. 为什么我需要像这样强制转换返回值

    返回(TaskService)taskAService;

  2. 是否有另一种无需执行强制转换即可实现getTaskService()方法的方法?

如果有人能为getTaskService方法提供一些解释或更好的实现,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

怎么样?

  • 不需要任何条件。
  • 以后如果有人确实添加了BaseTask的另一种实现,则不必更改任何其他代码。
  • 我还建议将“ atype”更改为Enum并使用Map<EnumTask, ? extends BaseTask> serviceMap;而不是String。

您对Tasks的最终调用可以不作任何检查

@Service
class ProcessingService { 

        @Autowired 
        private TaskServiceManager taskServiceManager;

        public void process(Order o){
            taskServiceManager.getServiceTask(o.type).start(task);
        }
}

其他课程

enum ServiceEnum {
    TaskA,
    TaskB
}

public class TaskA extends BaseTask {....}
public class TaskB extends BaseTask {....}

public abstract class TaskService<T extends BaseTask>{

    public TaskService(ServiceEnum serviceEnum, TaskServiceManager taskServiceManager) {
        taskServiceManager.registerTask(serviceEnum, this);
    }
    void process(T task);
}

@Service @Qualifier("taskServiceA")
public class TaskServiceA<TaskA> implements TaskService<TaskA>{
        @Autowired 
        public TaskA(TaskServiceManager taskServiceManager) {
              super(ServiceEnum.TaskA, taskServiceManager);
        }
}

@Service @Qualifier("taskServiceB")
public class TaskServiceB<TaskB> implements TaskService<TaskB>{...}

@Service
class  TaskServiceManager {
    Map<ServiceEnum, ? extends TaskService> serviceMap;

    public <T extends TaskService> void registerTask(ServiceEnum serviceName, T task) {
        if(serviceMap.containsKey(serviceName)) {
            throw new IllegalArgumentException("ServiceName is already in the Map");
        }
        serviceMap.put(serviceName, task);
    }

    public <T extends TaskService> T getServiceTask(ServiceEnum serviceName) {
        if(!serviceMap.containsKey(serviceName)) {
            throw new IllegalArgumentException("ServiceName is not Registered");
        }
        return serviceMap.get(serviceName);
    }
}

答案 1 :(得分:1)

因为在任何使用该方法的位置都将解析类型T。以下语句是有效的:

    TaskService<TaskA> s = getTaskService(o);

也是这样:

    TaskService<TaskB> s = getTaskService(o);

因此在getTaskService方法中,您对T的了解不多。

正确的方法是:

private TaskService<? extends BaseTask> getTaskService(Order o) {
    if ("atype".equals(o.type)) {
        return taskAService;
    } else if ("btype".equals(o.type)) {
        return taskBService;
    } else {
        return null;
    }
}

上面的分配必须变成:

TaskService<? extends BaseTask> s = getTaskService(o);