Универсальные интерфейсы Java с несколькими реализациями - PullRequest
0 голосов
/ 13 ноября 2018

У меня следующий сценарий:

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. Зачем мне приводить возвращаемое значение следующим образом

    return (TaskService) taskAService;

  2. Есть ли ещеспособ реализации метода getTaskService () без необходимости приведения?

Я буду очень признателен, если кто-нибудь сможет дать какое-то объяснение или лучшую реализацию для метода getTaskService.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Поскольку тип 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);
0 голосов
/ 13 ноября 2018

Как насчет этого?

  • Нет необходимости в каких-либо условиях.
  • Позже, если кто-то добавляет другую реализацию 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...