Java:程序开发中if else多层嵌套的优化

if else作为每种编程语言都不可或缺的条件语句,我们在编程时会大量的用到。但if else一般不建议嵌套超过三层,如果一段代码存在过多的if else嵌套,代码的可读性就会急速下降,后期维护难度也大大提高。所以,程序员都应该尽量避免过多的if else嵌套。下面将会简单谈谈如何减少if else的嵌套。

业务场景:分享一条新闻的标题,内容,链接。
业务基础类:如下

private static final int TYPE_TITLE = 0;
private static final int TYPE_CONTENT = 1;
private static final int TYPE_LINK = 2;

public class NewItem {
    int type;
    String title;
    String content;
    String link;
}

public interface ShareNewListener {
    int STATE_SUCC = 0;
    int STATE_FAIL = 1;

    void onCallback(int state, String message);
}

业务实现:如下

public void share (NewItem item, ShareNewListener listener) {
    if (item != null) {
        if (item.type == TYPE_LINK) {
            // 分享链接
            if (item.link != null) {
                doShareLink(item.link, item.content, listener);
            } else {
                if (listener != null) {
                    listener.onCallback(ShareNewListener.STATE_FAIL, "分享信息不完整");
                }
            }
        } else if (item.type == TYPE_TITLE ) {
            // 分享标题
            if (item.title != null)) {
                doShareText(item.title, listener);
            } else {
                if (listener != null) {
                    listener.onCallback(ShareNewListener.STATE_FAIL, "分享信息不完整");
                }
            }
        } else if (item.type == TYPE_CONTENT) {
            // 分享内容
            if (item.content != null) {
                doShareImageAndText(item.content, listener);
            } else {
                if (listener != null) {
                    listener.onCallback(ShareNewListener.STATE_FAIL, "分享信息不完整");
                }
            }
        } else {
            if (listener != null) {
                listener.onCallback(ShareNewListener.STATE_FAIL, "不支持的分享类型");
            }
        }
    } else {
        if (listener != null) {
            listener.onCallback(ShareNewListener.STATE_FAIL, "NewItem 不能为 null");
        }
    }
}

if else嵌套一般是为了解决空值判断,业务判断,状态判断等问题。针对这些问题可以通过下述方法进行优化:

方法一:接口分层

所谓接口分层指的是:把接口分为外部和内部接口,所有空值判断放在外部接口完成,只处理一次;而内部接口传入的变量由外部接口保证不为空,从而减少空值判断。

public void share(NewItem item, ShareNewListener listener) {
    if (item == null) {
        if (listener != null) {
            listener.onCallback(ShareNewListener.STATE_FAIL, "ShareItem 不能为 null");
        }
        return;
    }

    if (listener == null) {
        return;
    }

    shareImpl(item, listener);
}

private void shareImpl(ShareItem item, ShareNewListener listener) {
    if (item.type == TYPE_LINK) {
        // 分享链接
        if (item.link != null) {
            doShareLink(item.link, item.content, listener);
        } else {
            if (listener != null) {
                listener.onCallback(ShareNewListener.STATE_FAIL, "分享信息不完整");
            }
        }
    } else if (item.type == TYPE_TITLE ) {
        // 分享标题
        if (item.title != null)) {
            doShareText(item.title, listener);
        } else {
            if (listener != null) {
                listener.onCallback(ShareNewListener.STATE_FAIL, "分享信息不完整");
            }
        }
    } else if (item.type == TYPE_CONTENT) {
        // 分享内容
        if (item.content != null) {
            doShareImageAndText(item.content, listener);
        } else {
            if (listener != null) {
                listener.onCallback(ShareNewListener.STATE_FAIL, "分享信息不完整");
            }
        }
    } else {
        if (listener != null) {
            listener.onCallback(ShareNewListener.STATE_FAIL, "不支持的分享类型");
        }
    }
}

方法二:多态

利用多态,每种业务单独处理,在接口不再做任何业务判断。

private static final int TYPE_TITLE = 0;
private static final int TYPE_CONTENT = 1;
private static final int TYPE_LINK = 2;

public abstract class NewItem {
    int type;
    String title;
    String content;
    String link;

    public NewItem(int type,String title,String content,String link) {
        this.type = type;
        this.title=title;
        this.content=content;
        this.link=link;
    }

    public abstract void doShare(ShareNewListener listener);
}

public class New_Title extends NewItem {
    String title;

    public Link(String title) {
        super(TYPE_TITLE);
        this.title = title!=null ? title : "default";
    }

    @Override
    public void doShare(ShareNewListener listener) {
         listener.onCallback(ShareNewListener.STATE_SUCC, title);
    }
}

public class New_Content extends NewItem {
    String content;

    public Link(String content) {
        super(TYPE_CONTENT);
        this.content = content!=null ? content : "default";
    }

    @Override
    public void doShare(ShareNewListener listener) {
         listener.onCallback(ShareNewListener.STATE_SUCC, content);
    }
}

public class New_Link extends NewItem {
    String link;

    public Link(String link) {
        super(TYPE_LINK);
        this.link = link!=null ? link : "default";
    }

    @Override
    public void doShare(ShareNewListener listener) {
         listener.onCallback(ShareNewListener.STATE_SUCC, link);
    }
}

public void share(NewItem item, ShareNewListener listener) {
    if (item == null) {
        if (listener != null) {
            listener.onCallback(ShareNewListener.STATE_FAIL, "ShareItem 不能为 null");
        }
        return;
    }

    if (listener == null) {
        return;
    }

    shareImpl(item, listener);
}

private void shareImpl(NewItem item, ShareNewListener listener) {
    item.doShare(listener);
}

public ShareItem createNew_TitleItem(String title) {
    return new New_Title(title);
}
public ShareItem createNew_ContentItem(String content) {
    return new New_Content(content);
}
public ShareItem createNew_LinkItem(String link) {
    return new New_LinkItem(link);
}

方法三:使用Map替代分支语句

把所有分享子类型预先缓存在Map里,那么就可以直接get获取具体类型,消除分支

private Map<Integer, Class<? extends NewItem>> map = new HashMap<>();

private void init() {
    map.put(TYPE_TITLE, Title.class);
    map.put(TYPE_CONTENT, Content.class);
    map.put(TYPE_LINK, Link.class);
}

public NewItem createNewItem(int type) {
    try {
        Class<? extends NewItem> NewItemClass = map.get(type);
        return NewItemClass.newInstance();
    } catch (Exception e) {
        return new NewItem(); // 返回默认父类,不要返回null
    } 
}

总结

1.把接口分为外部和内部接口,所有空值判断放在外部接口完成;而内部接口传入的变量由外部接口保证不为空,从而减少空值判断。

2.利用多态,把业务判断消除,各子类分别关注自己的实现,并实现子类的创建方法,避免用户了解过多的类。

3.把分支状态信息预先缓存在Map里,直接get获取具体值,消除分支。

参考:https://mp.weixin.qq.com/s/vbJi0mqxYSVchMCzZ5FOpQ