Java:プログラム開発におけるif else多層ネストの最適化


Java:プログラム開発におけるif else多層ネストの最適化
if elseは各プログラミング言語に不可欠な条件文として、プログラミング時に大量に使用されます.しかしif elseは一般的にネストが3層を超えることをお勧めしません.一部のコードに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ネストは,一般に空値判断,業務判断,状態判断などの問題を解決するためである.これらの問題に対して、以下の方法で最適化することができる.
方法1:インタフェースの階層化
インタフェース階層とは、インタフェースを外部と内部のインタフェースに分け、すべての空値判断を外部のインタフェースに置いて完了し、一度だけ処理することを指す.一方、内部インタフェースから入力される変数は、外部インタフェースによって空でないことを保証し、空値判断を低減する.
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, "        ");
        }
    }
}

方法2:マルチステート
マルチステートを用いて,各業務を個別に処理し,インタフェースでは業務判断を行わない.
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);
}

方法3:分岐文の代わりにMapを使用する
すべての共有サブタイプをMapに保存しておくと、直接getで特定のタイプを取得し、ブランチを除去することができます.
private Map> 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