Java 如何避免很多if-else条件
我读过很多关于代码重构和避免if-else语句的主题。实际上,我在一个类中使用了很多if-else条件 更多细节:我正在使用pull解析器,在我的soap响应的每一行上,我将检查是否有我感兴趣的标记,如果没有,检查另一个标记,等等:Java 如何避免很多if-else条件,java,if-statement,refactoring,Java,If Statement,Refactoring,我读过很多关于代码重构和避免if-else语句的主题。实际上,我在一个类中使用了很多if-else条件 更多细节:我正在使用pull解析器,在我的soap响应的每一行上,我将检查是否有我感兴趣的标记,如果没有,检查另一个标记,等等: if(eventType == XmlPullParser.START_TAG) { soapResponse= xpp.getName().toString(); if (soapResp
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条件,但我不知道是什么
你能给我举个例子吗?除了zzzzz(等)的评论之外。。。请记住,您使用的是XmlPullParser,这会让您编写出与现有代码类似的难看代码。您可以注册一些回调来拆分代码并使其“更好”,但如果可能,只需使用SimpleXML库或类似工具即可
此外,您还可以重构代码,使其更具可读性,更不冗长。例如,为什么在每个if语句中调用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();
在Java7中,可以打开字符串。如果可以的话,你可以用它;-) 试着看看战略模式
- 创建用于处理响应的接口类(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());
您可以创建一个带有三个实现的ResponseHandler接口,分别用于if/else构造的每个分支 然后创建一个映射,将不同的soapResponse映射到一个处理程序,或者如果可以处理该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);
}
List handlers=Arrays.asList(
新的负责人(“编辑部”),
新负责人(“编辑委员会”),
新负责人(“咨询委员会”);
if(eventType==XmlPullParser.START_标记){
对于(响应处理程序h:处理程序)
h、 手柄(xpp);
}
这是一个巨大的问题,没有真正的答案。(我不经常用肥皂)
以下是基于您的代码的一些想法:
首先,您可以将重复代码分组
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();
}
....}
这样你就可以在一个while循环中处理你的所有答案,然后你就可以把if-else变成一个5~10行的函数
但是,正如我所说,在这个特殊的情况下,有很多很好的方法可以做同样的事情,因为除了所附加的字符串之外,所有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
没有“如果……那么……其他”。甚至连策略模式等多个类的复杂性都没有。地图是你的朋友。在某些情况下,策略是很好的,但是这个策略非常简单,可以不用它来解决。您没有提到是否可以或确实使用Java 7。从java版本开始,您可以使用 除此之外,封装每个案例的逻辑是一个好主意,例如:
Map strategyMap=newhashmap();
战略地图放置(“编辑办公室”,新编辑办公室());
战略地图放置(“编辑板”,新编辑板部门());
战略地图放置(“公告板”,新公告板部门());
然后,您只需从地图中选择正确的策略并使用它:
String soapResponse = xpp.getName();
Department department = strategyMap.get(soapResponse);
department.addText(xpp.getText());
部门
当然在接口中…您可以定义如下所示的枚举:
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);
}
这是干净的代码,不是吗 您可以在程序的其他地方维护字符串到枚举的映射,从映射中取出与返回字符串相关联的枚举(如果字符串不在映射中,则使用默认的
NO_MATCH
),并在枚举上写入switch语句。它可能会使代码更清晰,但会牺牲额外的间接层。您必须判断这是否值得。检查:希望这是一个有用的提示,出于性能原因,您应该使用StringBuilder而不是+=来连接字符串。谢谢Sam Barnum,如何使用字符串生成器?我将尝试在internet上查看,但一个示例将非常有用。StringBuilder sb=new StringBuilder();某人(编辑委员会);sb.append(xpp.getText);编辑板=sb.toString()代码>谢谢@Cristian,事实上,我正在从服务器获得xml响应,我不知道是否可以使用其他东西,这就像xml拉式解析器一样精巧。我正在对每个语句调用xpp.next(),而当找到我要查找的开始标记时,我将在下一行找到我需要的变量,并将其放入我的局部变量中。还返回String
,因此无需对其调用.toString()
。@Ana只要看看SimpleXML库;这会让你的生活更轻松、更快乐。@Cristian,再次感谢你,你有如何使用这个的例子吗?文档非常完整。一旦您设置好了所有内容,就可以像执行以下操作一样简单:SomeObject oneObject=Xml.parse(SomeObject.class,xmlPayload)代码>谢谢@hwcverwe,我觉得这是个好主意。你能给我一个更精确的例子说明如何做到这一点吗?非常感谢。也许这适用于更复杂的多条件决策。但是对于这个特殊的案例来说,这不觉得太沉重了吗?见鬼,我甚至更喜欢“如果,那么
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);
}