Как избежать многих условий 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);
}
Это чистый код, не так ли!