Перемещение общего кода между двумя реализациями интерфейса - PullRequest
0 голосов
/ 12 июля 2020

У меня есть интерфейс, называемый процессором:

public interface Processor {
    MyResponse process(Request request, String id);
}

У меня есть две реализации этого процессора, одна синхронная, другая асинхронная (оба класса Spring Service):

Это Syn c Версия, завершает задание и дает полностью заполненный ответ:

@Service
public class SynchrnousProcess implements Processor {

    @Override
    public MyResponse process(Request request, String id) {
        Job job = getJob(request);
        JobParameters parameter = buildParams(request, id);
        JobExecution jobExecution = kickOfJob(job, request, parameter);
        return buildResponse(request, trackingId, jobExecution);
    }    
}

Это версия Asyn c, которая добавляет запросы в очередь блокировки:

@Service
public class AsyncProcess implements Processor {


     private BlockingQueue<Pair> requestQueue = new ArrayBlockingQueue<>(100);

    @Override
    public MyResponse process(Request request, String id) {
     //add request to requestQueue 
    }    

    public void completeProcess() {
    //take data from queue and process
    log.info("start process !!!!!!!!!!!!!!!");
    if (!CollectionUtils.isEmpty(requestQueue)) {
        requestQueue.stream().forEach(pair -> {
            String trackingId = String.valueOf(pair.getFirst());

            FeedDto feedDto = (FeedDto) pair.getSecond();
            Request request = feedDto.getRequest();
            Job job = getJob(request);

            JobParameters parameter = getJobParameters(request, trackingId);
            JobExecution jobExecution = runJob(job, request, parameter);
    }
}

Как вы можете см., completeProcess() берет данные из очереди и обрабатывает задание. Общий код для получения задания, параметры построения дублируются между синхронным запуском и asyn c.

Другой поток запускается completeProcess() в фоновом режиме.

Я хочу добиться чистого дизайна и переместить общий код, который используется двумя реализациями интерфейса, в одно место. Как я могу добиться этого в том, чего я пытаюсь достичь? Будет действительно полезно увидеть пример шаблона проектирования, который будет использоваться в этом случае?

Кроме того, любые предложения относительно того, где должен быть инициирован ExecutorService для обработки запросов в очереди и как потоки для их обработки надо начинать, очень поможет.

1 Ответ

0 голосов
/ 12 июля 2020

Вы можете разработать интерфейс, поскольку он должен выполнять асинхронные c операции. Например:

public interface Callback() {
    void onResponse(MyResponse mr);
}

public void Processor {
    void process(Request request, String id, Callback callback);
}

@Service
public class SynchrnousProcess implements Processor {

    @Override
    public void process(Request request, String id, Callback callback) {
        Job job = getJob(request);
        JobParameters parameter = buildParams(request, id);
        JobExecution jobExecution = kickOfJob(job, request, parameter);
        MyResponse r = buildResponse(request, trackingId, jobExecution);
        callback.onResponse(r);
    }    
}

@Service
public class AsyncProcess implements Processor {


     private BlockingQueue<Pair> requestQueue = new ArrayBlockingQueue<>(100);

    @Override
    public void process(Request request, String id, Callback callback) {
     //add request and callback to requestQueue 
    }    

}

Я не знаю, кто будет обрабатывать очередь, но наверняка, кто будет использовать процессор, не должен беспокоиться, синхронный вызов или нет.

это наиболее похожий на тот подход, который вы использовали бы в C# с asyn c await. В C# вы должны вернуть Task даже в синхронном случае. Тогда потребитель всегда будет думать, что вызов будет асинхронным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...