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

Я прочитал много тем о рефакторинге кода и избежании операторов if else. На самом деле, у меня есть класс, где я использую много условий 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, но я не знаю, что.

Can вы, пожалуйста, дайте мне пример или хорошую страницу учебника?

спасибо.

8 ответов


в этом конкретном случае, поскольку код по существу идентичен для всех 3 случаев, за исключением строки, к которой добавляется, у меня будет запись карты для каждой из строящихся строк:

Map<String,String> map = new HashMap<String,String>();
map.put("EditorialOffice","");
map.put("EditorialBoard","");
map.put("AdvisoryBoard","");
// could make constants for above Strings, or even an enum

а затем измените свой код на следующий

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

нет "если... затем... еще." Даже не добавленная сложность нескольких классов для шаблонов стратегий и т. д. Карты - твой друг. Стратегия хороша в некоторых ситуациях, но эта достаточно проста, чтобы быть решена без.


попробуйте взглянуть на шаблон стратегии.

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

мало Пример:

// Interface
public interface IResponseHandler {
   public void handleResponse(XmlPullParser xxp);

}

// Concrete class for EditorialOffice response
private class EditorialOfficeHandler implements IResponseHandler {
   public void handleResponse(XmlPullParser xxp) {
       // Do something to handle Editorial Office response
   }
}

// Concrete class for EditorialBoard response
private class EditorialBoardHandler implements IResponseHandler {
   public void handleResponse(XmlPullParser xxp) {
       // Do something to handle Editorial Board response
   }
}

на месте вам нужно создать обработчики:

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);

в Java 7 Вы можете включить строки. Вы могли бы использовать это, если бы вы могли использовать это ; -)


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

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

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();

вы не упомянули, можете ли вы или используете Java 7. Начиная с этой версии java вы можете использовать строки в операторах switch.

кроме этого, инкапсулирование логики для каждого случая является хорошей идеей, например:

Map<String, Department> strategyMap = new HashMap<String, Department>();
strategyMap.put("EditorialOffice", new EditorialOfficeDepartment());
strategyMap.put("EditorialBoard", new EditorialBoardDepartment());
strategyMap.put("AdvisoryBoard", new AdvisoryBoardDepartment());

затем вы можете просто выбрать правильную стратегию с карты и использовать его:

String soapResponse = xpp.getName();
Department department = strategyMap.get(soapResponse);
department.addText(xpp.getText());

Department конечно, в интерфейсе...


обширный вопрос, который является этим, и нет реального ответа. (и я не очень часто использую мыло)

вот только некоторые идеи, основанные на вашем коде:

сначала вы можете сгруппировать дубликат кода

if (soapResponse.equals("EditorialOffice")
||soapResponse.equals("EditorialBoard")
||soapResponse.equals("AdvisoryBoard")){ 

еще одна хорошая вещь, которую вы можете сделать, это поиграть с переключателями, такими как:

switch(soapResponse){
case "EditorialOffice":
case "EditorialBoard":
case "AdvisoryBoard":
eventType = xpp.next();
                if (xpp.getText()!=null){
                advisoryBoard += xpp.getText();
                }
break;

также вы должны рассмотреть возможность разбиения теста на небольшие функции:

public bool interestingTag(string s){
return (soapResponse.equals("EditorialOffice")
    ||soapResponse.equals("EditorialBoard")
    ||soapResponse.equals("AdvisoryBoard"));
}

    public processData(xpp){
    eventType = xpp.next();
                    if (xpp.getText()!=null){
                    editorialBoard += xpp.getText();
                    }
    ....}

Так что вы можете просто обработать все свои ответы в в то время как цикл и вы супер долго, если еще становится 5~10 line function

но, как я уже сказал, Есть так много хороших способов сделать то же самое


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

затем либо сопоставьте различные soapResponses с обработчиком, либо список со всем обработчиком, если он может обрабатывать этот soapResponse.

вы также должны иметь возможность переместить часть шаблонного кода в общую, возможно, абстрактную реализацию класса обработчика ответов.

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

class ResponseHandler{
    String stringToBuild = "" // or what ever you need
    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){
                 editorialOffice += 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);
}

вы можете определить перечисление следующим образом:

public enum SoapResponseType {
    EditorialOffice(1, "description here") {
        public void handle(XmlPullParser xpp) {
            //do something you want here
            return null;
        }
    },
    EditorialBoard(2, "description here") {
        public void handle(XmlPullParser xpp) {
            //do something you want here
            return null;
        }
    },
    AdvisoryBoard(3, "description here") {
        public void handle(XmlPullParser xpp) {
            //do something you want here
            return null;
        }
    };

    public static SoapResponseType nameOf(String name) {
        for (SoapResponseType type : values()) {
            if (type.getName().equalsIgnoreCase(name)) {
                return type;
            }
        }
        return null;
    }

    public void handle(XmlPullParser xpp) {
        return null;
    }
}

используйте выше перечисление, как это:

SoapResponseType type = SoapResponseType.nameOf("input string");
if (type != null) {
    type.handle(xpp);
}

Это чистый код, не так ли!