0

Как избежать множества условий if-else?

10

Я прочитал много материалов о рефакторинге кода и о том, как избежать использования условных операторов if-else. У меня есть класс, в котором я использую много таких условий.

Вот подробнее: я использую парсер, и для каждой строки в моем SOAP-ответе я проверяю, есть ли интересующий меня тег. Если нет, то проверяю другой тег и так далее:

if(eventType == XmlPullParser.START_TAG) {
    soapResponse= xpp.getName().toString();
    
    if (soapResponse.equals("EditorialOffice")){  
        eventType = xpp.next();
        if (xpp.getText() != null) {
            editorialOffice += xpp.getText();
        }
    }   
    else if (soapResponse.equals("EditorialBoard")){  
        eventType = xpp.next();
        if (xpp.getText() != null) {
            editorialBoard += xpp.getText();
        }
    }
    else if (soapResponse.equals("AdvisoryBoard")){  
        eventType = xpp.next();
        if (xpp.getText() != null) {
            advisoryBoard += xpp.getText();
        }
    }   
}
eventType = xpp.next();

Теперь я хотел бы использовать что-то другое вместо этих условий if-else, но не знаю, что именно. Можете ли вы привести пример?

5 ответ(ов)

0

Попробуйте рассмотреть шаблон стратегии.

  • Создайте интерфейс для обработки ответов (IMyResponse).
    • Используйте этот IMyResponse для создания классов AdvisoryBoardResponse и EditorialBoardResponse.
  • Создайте словарь, где ключом будет значение soapresponse, а значением - ваша стратегия.
  • Затем вы сможете использовать методы класса IMyResponse, получая его из словаря.

Небольшой пример:

// Интерфейс
public interface IResponseHandler {
   public void handleResponse(XmlPullParser xxp);
}

// Конкретный класс для обработки ответа редакционной коллегии
private class EditorialOfficeHandler implements IResponseHandler {
   public void handleResponse(XmlPullParser xxp) {
       // Реализуйте логику обработки ответа редакционной коллегии
   }
}

// Конкретный класс для обработки ответа редакционного совета
private class EditorialBoardHandler implements IResponseHandler {
   public void handleResponse(XmlPullParser xxp) {
       // Реализуйте логику обработки ответа редакционного совета
   }
}

В месте, где необходимо создать обработчики:

Map<String, IResponseHandler> strategyHandlers = new HashMap<String,IResponseHandler>();
strategyHandlers.put("EditorialOffice", new EditorialOfficeHandler());
strategyHandlers.put("EditorialBoard", new EditorialBoardHandler());

Когда вы получили ответ:

IResponseHandler responseHandler = strategyHandlers.get(soapResponse);
responseHandler.handleResponse(xxp);

Это позволит вам легко добавлять новые обработчики в будущем, просто создавая новые классы, реализующие интерфейс IResponseHandler и добавляя их в словарь.

0

В данном случае, поскольку код почти идентичен для всех трех случаев, кроме строки, к которой добавляется текст, я бы использовал карту (Map) для каждой из строк, которые мы собираем:

Map<String, String> map = new HashMap<String, String>();
map.put("EditorialOffice", "");
map.put("EditorialBoard", "");
map.put("AdvisoryBoard", "");
// можно использовать константы для строк выше или даже перечисление (enum)

А затем изменил бы ваш код на следующий:

if (eventType == XmlPullParser.START_TAG) {
    soapResponse = xpp.getName().toString();
    String current = map.get(soapResponse);
    if (current != null && xpp.getText() != null) {
        map.put(soapResponse, current += xpp.getText());
    }
    eventType = xpp.next();
}

Так вы избежите "if... then... else". Не нужно добавлять лишнюю сложность в виде множественных классов для паттернов стратегий и т.д. Карты (Maps) — ваш надежный помощник. Паттерн стратегии может быть полезен в некоторых ситуациях, но в этом случае задача достаточно проста, чтобы решить её без него.

0

В Java 7 можно использовать оператор SWITCH с объектами типа String. Это может быть полезным, если вы хотите сделать выбор между несколькими строковыми значениями. Например:

String fruit = "apple";

switch (fruit) {
    case "apple":
        System.out.println("You chose an apple.");
        break;
    case "banana":
        System.out.println("You chose a banana.");
        break;
    case "orange":
        System.out.println("You chose an orange.");
        break;
    default:
        System.out.println("Unknown fruit.");
}

Такой подход делает код более читаемым и удобным для понимания, особенно если у вас много вариантов для сравнения. Просто помните, что SWITCH с строками начинает работать с Java 7, так что убедитесь, что ваш проект использует эту или более позднюю версию.

0

Кроме комментария zzzzzzz(и других), учтите, что вы используете XmlPullParser, что приводит к написанию довольно неаккуратного кода. Вы можете зарегистрировать несколько обратных вызовов, чтобы разбить ваш код на более читаемые части, но лучше всего использовать библиотеку SimpleXML или что-то подобное, если это возможно.

Также вы можете отрефакторить свой код, чтобы сделать его более читаемым и менее многословным. Например, зачем вы вызываете xpp.next() внутри каждого условия? Почему бы не сделать это один раз вне условий:

if(eventType == XmlPullParser.START_TAG) {
    soapResponse = xpp.getName().toString();
    if (soapResponse.equals("EditorialOffice") && xpp.getText() != null) {  
        editorialOffice += xpp.getText();
    }   
    else if (soapResponse.equals("EditorialBoard") && xpp.getText() != null) {  
        editorialBoard += xpp.getText();
    }
    else if (soapResponse.equals("AdvisoryBoard") && xpp.getText() != null) {  
        advisoryBoard += xpp.getText();
    }   
}
eventType = xpp.next();

Такой подход упростит ваш код и сделает его более понятным.

0

Вы можете создать интерфейс ResponseHandler с тремя реализациями, по одной для каждого ветвления в вашем конструктиве if/else.

Затем можно использовать карту, которая связывает разные soapResponses с обработчиком, или список, содержащий все обработчики, если они могут обрабатывать данный soapResponse.

Также стоит переместить часть повторяющегося кода в общее абстрактное представление класса обработчика ответов.

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

class ResponseHandler {
    String stringToBuild = ""; // или что-то, что вам нужно
    private final String matchString;

    ResponseHandler(String aMatchString) {
        matchString = aMatchString;
    }

    void handle(XppsType xpp) {
        if (xpp.getName().toString().equals(matchString)) {
            eventType = xpp.next();
            if (xpp.getText() != null) {
                stringToBuild += xpp.getText();
            }
        }
    }
}

Ваш код становится:

List<ResponseHandler> handlers = Arrays.asList(
    new ResponseHandler("EditorialOffice"),
    new ResponseHandler("EditorialBoard"),
    new ResponseHandler("AdvisoryBoard")
);
if(eventType == XmlPullParser.START_TAG) {
    for(ResponseHandler h : handlers) {
        h.handle(xpp);
    }
}

Таким образом, ваш код становится более читаемым и структурированным, что упрощает добавление новых обработчиков в будущем.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь