Написание обработчика ответа в Java - PullRequest
3 голосов
/ 10 марта 2020

Моя служба вызывает нисходящую службу, которая возвращает ResponseEntity<MyBodyClass> response. Мой сервис должен реагировать по-разному в зависимости от различных свойств response

Например, если response.getStatusCode() == HttpStatus.BAD_REQUEST и response.getBody().code == 1, сервис должен выполнить какое-то действие «A», но если для одного и того же кода состояния response.getBody().id == 1, то следует сделать «Б». Другой пример: если response.getStatusCode() == HttpStatus.OK и response.getBody() != null, служба должна выполнить "C".

Я знаю, что это можно сделать с помощью множества операторов if, но есть ли лучший шаблон проектирования?

Ответы [ 2 ]

5 голосов
/ 10 марта 2020

Реализуйте правила как цепочку ответственности:

ruleFoo -> ruleBar -> ruleFooBar -> ....

Цепочка должна быть упорядочена в соответствии с приоритетом правила, и каждый элемент цепочки (правило здесь) обрабатывается для обнаружения совпадения. Как только правило совпадает, правило выполняет соответствующее действие и цепной процесс останавливается.

Здесь очень простая реализация, использующая преимущества потока java 8 (который немного отличается от исходного шаблона GOF, но мне нравится, потому что он легче для реализации).

public interface ResponseRule {        
    boolean match(Response response);                  
    void performAction();                          
}

public class RuleFoo implements ReponseRule {

    public boolean match(Response response){
       return response.getStatusCode() == HttpStatus.BAD_REQUEST && response.getBody().code == 1;
    }

    public void performAction(){
       // do the action
    }
}

public class RuleBar implements AbstractReponseRule {

    public boolean match(Response response){
       return response.getStatusCode() == HttpStatus.BAD_REQUEST && response.getBody() != null;
    }

    public void performAction(){
       // do the action
    }
}

И как их использовать:

Response response = ...;
List<ResponseRule> rules = new ArrayList<>();
rules.add(new RuleFoo(), new RuleBar());

rules.stream()
     .filter(rule -> rule.match(response))
     .findFirst()
     .ifPresent(ResponseRule::performAction);

Обратите внимание, что, если выполнение правил может быть накоплено, это потребует небольшого изменения:

rules.stream()
     .filter(rule -> rule.match(response))
     .forEachOrdered(ResponseRule::performAction);
1 голос
/ 10 марта 2020

Обычная техника - использовать класс "обработчик". Сначала вам нужен интерфейс:

interface ResponseHandler {
    // The order in which handlers are called
    int getPriority();
    // return true of the response is handled by this handler
    boolean handle(ResponseEntity<MyBodyClass> response);
}

Затем создайте несколько реализаций:

class BadRequestHandler implements ResponseHandler {
    public int getPriority() {
        return 1;
    }
    public boolean handle(ResponseEntity<MyBodyClass> response) {
        if (response.getStatusCode() == HttpStatus.BAD_REQUEST 
            && response.getBody().code == 1) {
            // do stuff to handle the request
            return true;
        }
        return false;
    }
}

Затем вам нужен их список, и вы l oop по списку пробуете каждый обработчик по очереди пока один не вернет true.

List<ResponseHandler> responseHandlers;
// add response handler implementations to the list and sort it.
for (int i = 0; i < responseHandlers.size() 
        && !responseHandlers.get(i).handle(response); i++);

Перед использованием списка вы должны отсортировать его по getPriority. Самый простой способ сделать это - также реализовать Comparable в объекте. См. Сортировка ArrayList пользовательских объектов по свойству .

Этот метод не будет столь же эффективным, как простое написание большого количества операторов if (поскольку вы, вероятно, можете учесть условия для удаления общих подусловий ), но он предлагает гибкость для более простого подключения новых обработчиков, и код может быть более читабельным.

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