我正在为我的Android设备构建一个HTTP服务器。
我使用了很多IF-ELSE语句来处理不同的请求。
由于我将与其他人分享我的代码供以后使用,我必须尽可能清晰。现在,我甚至无法轻松阅读我的代码。
我认为问题来自于在一个类中使用大量IF-ELSE语句。 例如。
if(purpose.equals("readProfile"){
.....
}
else if(purpose.equals("writeProfile"){
.....
}
....
我尝试在类别中对它们进行分类,并根据类别对条件进行排序。但并没有提高很多的可用性。 然后我尝试在每个条件面前写短评。但这让事情变得更加混乱。
如何提高条件语句的易读性?
答案 0 :(得分:4)
正如Luiggi Mendoza所述,这是对a previous question ...
的跟进如果您使用的是 Java 7 ,则可以使用switch-case statement for strings
//month is a String
switch (month.toLowerCase()) {
case "january":
monthNumber = 1;
break;
//partsleft out for sake of brevity ..
default:
monthNumber = 0;
break;
}
(摘自上面引用的Oracle Java教程。)
然而,这个巨大的if-else只是问题的一部分。由于这似乎是一个随着时间的推移而增长的结构,我建议进行彻底的重构,并使用我认为的Strategy pattern。你应该:
制定涵盖所有用例边界的界面:
interface MyStrategy {
void execute(MyInputContext input, MyOutputContext output);
}
(使用带有MyInputContext和MyOutputContext的void方法只是一种方法,这只是一个示例,但是为了处理具有响应的请求,这有意义,就像Servlet的工作方式一样)
将大IF-ELSE语句的内容重构为此接口的实例(这些将是策略):
//VERY simplified...
class ReadProfileStrategy implements MyStrategy {
void execute(MyInputContext input, MyOutputContext output) {
//do the stuff that was in the if-else block in the "readProfile" part
}
}
//... at the branching part:
MyInputContext input; //build this here
MyOutputContext output; //build this here
switch (purpose) {
case "readProfile":
// no need to always instantiate this, it should be stateless...
new ReadProfileStrategy().execute();
break;
//... left out for sake of brevity
}
如果这样做,您可以将字符串ID添加到接口,并将实例本身添加,并完全删除if-else或switch语句,您可以创建一个甚至通过IOC容器填充的Map(如) ,是最新的,并且完全灵活。
class ReadProfileStrategy implements MyStrategy {
String getID() {
return "readProfile";
}
void execute(MyInputContext input, MyOutputContext output) {
//do the stuff that was in the if-else block in the "readProfile" part
}
}
在处理请求的类中
private final Map<String, MyStrategy> strategyMap; //fill the map using your favorite approach, like using Spring application context, using the getCode() to provide the key of the map
在处理逻辑中:
MyStrategy strategy = strategyMap.get(purpose);
if(strategy!=null) {
strategy.execute();
}
else {
//handle error here
}
答案 1 :(得分:2)
这可能超出了范围,只是一个观察
尝试使用
if("readProfile".equals(purpose){}
而不是
if(purpose.equals("readProfile"){}
。
这将有助于避免null pinter异常
答案 2 :(得分:2)
枚举可以提供帮助 - 您还可以为它们添加功能。
public void test(String purpose) {
if (purpose.equals("readProfile")) {
// Read.
} else if (purpose.equals("writeProfile")) {
// Write.
}
}
enum Purpose {
readProfile {
@Override
void doIt() {
// Read.
}
},
writeProfile {
@Override
void doIt() {
// Write.
}
};
abstract void doIt();
}
public void test2(String purpose) {
Purpose.valueOf(purpose).doIt();
}
答案 3 :(得分:1)
您可以尝试使用某种Action-Interface和每个块的实现,并使用具体的此操作实现预加载地图。
interface Action {
void execute();
}
Map<String, Action> actions = new HashMap<>();
actions.put("readProfile", new Action() { ... });
actions.put("writeProfile", new Action() { ... });
actionMap.get(purpose).execute();
这也会降低你的圈复杂度。当然你应该只预加载一次地图。
答案 4 :(得分:1)
好吧,如果将if-else条件中的代码分离到另一个类是有意义的,也许使用Factory模式。还要使所有单独的类使用MyActivity.class
等方法实现公共接口(例如:execute()
)。
工厂决定必须根据您传递的字符串创建哪个对象(ReadProfile.class
,WriteProfile.class
等),然后调用execute()
方法。
MyActivity obj = MyFactory.createMyActivity(String)
obj.execute(...);