IF優化筆記(仿App分享SDK簡單封裝)

Ⅰ.前言

前些天在簡書上看了 “if嵌套優化” 的一文章,覺得蠻實用的也挺好玩的,抱着學習的心態看了幾遍,之後又給敲了一遍,然後就有了下面的純代碼筆記

學習博客: https://www.jianshu.com/p/57c065b124c4

Ⅱ.筆記

1.以微信分享來說,可以進行圖片、文字、圖文、鏈接、音樂等分享,假設這套SDK是我們寫的,或許會這麼寫,一堆的if嵌套:

package com.wyk.ifelse;

public class IfElse01 {

        private static final int TYPE_LINK = 0;
        private static final int TYPE_TEXT = 1;
        private static final int TYPE_IMAGE = 2;
        private static final int TYPE_IMAGE_TEXT = 3;

        static class ShareItem{
            int type;
            String title;
            String content;
            String imagePath;
            String link;
        }

        public interface ShareListener{
            int STATE_SUCC = 0;
            int STATE_FAIL = 1;
            void onCallback(int state,String msg);
        }

        public static ShareItem createShareItem() {
            return new ShareItem();
        }


    //分享的操作
    public static void share(ShareItem item,ShareListener listener) {
            if (item != null) {
                if (item.type == TYPE_LINK) {
                    // 分享鏈接
                    if (!TextUtils.isEmpty(item.link) && !TextUtils.isEmpty(item.title)) {
                        doShareLink(item.link, item.title, item.content, listener);
                    } else {
                        if (listener != null) {
                            listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                        }
                    }
                } else if (item.type == TYPE_IMAGE) {
                    // 分享圖片
                    if (!TextUtils.isEmpty(item.imagePath)) {
                        doShareImage(item.imagePath, listener);
                    } else {
                        if (listener != null) {
                            listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                        }
                    }
                } else if (item.type == TYPE_TEXT) {
                    // 分享文本
                    if (!TextUtils.isEmpty(item.content)) {
                        doShareText(item.content, listener);
                    } else {
                        if (listener != null) {
                            listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                        }
                    }
                } else if (item.type == TYPE_IMAGE_TEXT) {
                    // 分享圖文
                    if (!TextUtils.isEmpty(item.imagePath) && !TextUtils.isEmpty(item.content)) {
                        doShareImageAndText(item.imagePath, item.content, listener);
                    } else {
                        if (listener != null) {
                            listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                        }
                    }
                } else {
                    if (listener != null) {
                        listener.onCallback(ShareListener.STATE_FAIL, "不支持的分享類型");
                    }
                }
            } else {
                if (listener != null) {
                    listener.onCallback(ShareListener.STATE_FAIL, "ShareItem 不能爲 null");
                }
            }

      }
}

2.上面是不是一堆的if-else嵌套,這樣子不僅不美觀,而且維護成本也很高,如果是作爲SDK,更不能用這種形式來寫,接着以 “開設內外接口的方式來減少if-else”:


package com.wyk.ifelse;

import com.wyk.ifelse.IfElse01.ShareItem;
import com.wyk.ifelse.IfElse01.ShareListener; 

public class IfElse02 {

        private static final int TYPE_LINK = 0;
        private static final int TYPE_TEXT = 1;
        private static final int TYPE_IMAGE = 2;
        private static final int TYPE_IMAGE_TEXT = 3;

        //外接口
        public void share(ShareItem item,ShareListener listener) {
            if(item == null) {
                if(listener != null) {
                    listener.onCallback(ShareListener.STATE_FAIL, "ShareItem 不能爲 null"); 
                }
                return;
            }
            if(listener == null){
                listener = new ShareListener() {
                    @Override
                    public void onCallback(int state, String msg) {
                        //System.out.println("state : " + state + ", msg : " + msg); 
                    }
                };
            }

            shareImpl(item,listener); 
    }

    //內接口
    public void shareImpl(ShareItem item,ShareListener listener){
            if (item.type == TYPE_LINK) {
                // 分享鏈接
                if (!TextUtils.isEmpty(item.link) && !TextUtils.isEmpty(item.title)) {
                    doShareLink(item.link, item.title, item.content, listener);
                } else {
                    listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                }
            } else if (item.type == TYPE_IMAGE) {
                // 分享圖片
                if (!TextUtils.isEmpty(item.imagePath)) {
                    doShareImage(item.imagePath, listener);
                } else {
                    listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                }
            } else if (item.type == TYPE_TEXT) {
                // 分享文本
                if (!TextUtils.isEmpty(item.content)) {
                    doShareText(item.content, listener);
                } else {
                    listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                }
            } else if (item.type == TYPE_IMAGE_TEXT) {
                // 分享圖文
                if (!TextUtils.isEmpty(item.imagePath) && !TextUtils.isEmpty(item.content)) {
                    doShareImageAndText(item.imagePath, item.content, listener);
                } else {
                    listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整");
                }
            } else {
                listener.onCallback(ShareListener.STATE_FAIL, "不支持的分享類型");
            }
        }


}

3.上面這樣將listener是否爲null,單獨在外接口裏判斷,確實使得內接口減少了if-else嵌套,但減少得也不多,還是好幾層if-else,接着 用Java”多態” 的特性來玩玩:


package com.wyk.ifelse.sdk;
import com.wyk.ifelse.IfElse01.ShareListener;

public class IfElse03 {

        private static final int TYPE_LINK = 0;
        private static final int TYPE_TEXT = 1;
        private static final int TYPE_IMAGE = 2;
        private static final int TYPE_IMAGE_TEXT = 3;

        public static abstract class ShareItem{
            int type;
            public ShareItem(int type) {
                this.type = type;
            }
            public abstract void doShare(ShareListener listener);
        }

        //分享鏈接
        public static class Link extends ShareItem{
            String mLink;
            String mTitle;
            String mContent;
            public Link(String link,String title,String content) {
                super(TYPE_LINK);
                this.mLink = (link !=null && link !="")? link : "default";
                this.mTitle = (title != null && title != "")? title : "default";
                this.mContent = (content != null && content != "")? content : "default";
            }
            @Override
            public void doShare(ShareListener listener) {
                if(listener == null) {
                    return;
                }
                if(mLink == "default" || mTitle == "default" || mContent == "default") {
                    listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整"); 
                    return;
                }
                listener.onCallback(ShareListener.STATE_SUCC, "鏈接 分享成功3");
            }
        }

    //分享圖片
    public static class Image extends ShareItem{
            String imagePath;
            public Image(String imagePath) {
                super(TYPE_IMAGE);
                this.imagePath = (imagePath != null && imagePath != "")? imagePath : "default";
            }
            @Override
            public void doShare(ShareListener listener) { 
                //TODO
            }
        }

    //分享文字
    public static class Text extends ShareItem{
            String content;
            public Text(String content){
                super(TYPE_TEXT);
                this.content = (content != null && content != "")? content : "default";
            }
            @Override
            public void doShare(ShareListener listener) { 
                //TODO
            }
        }

    //分享圖文
    public static class ImageText extends ShareItem{
            String imagePath;
            String content;
            public ImageText(String imagePath, String content){
                super(TYPE_IMAGE_TEXT);
                this.imagePath = (imagePath != null && imagePath != "")? imagePath : "default";
                this.content = (content != null && content != "")? content : "default";
            }
            @Override
            public void doShare(ShareListener listener) { 
                //TODO
            }
        }

          ////////////////////////////////////////////////////////////////////////////

    //分享的操作
    public void share(ShareItem item,ShareListener listener) {
            if(item == null) {
                if(listener != null) { 
                    listener.onCallback(ShareListener.STATE_FAIL, "ShareItem 不能爲 null"); 
                }
                return;
            }
            if(listener == null) {
                listener = new ShareListener() {
                    @Override
                    public void onCallback(int state, String msg) {
                        System.out.println("ShareListener is null"); 
                    }
                };
            }
            shareImpl(item, listener); 
        }

        public void shareImpl(ShareItem item,ShareListener listener) {
            item.doShare(listener); 
        }

}

這下子終於沒看到多層if-else嵌套咯,把ShareItem進行抽象,然後供子類繼承並各自實現操作,不好的是使用者得清楚哪些類對應哪些操作,才能創建類從而執行相應的操作,比如Link類是對應的鏈接分享,ImageText類是對應的文字分享等,這個就不太好了,怎麼解決呢?

缺點:多個類對外開放,如果是sdk的形式給使用者使用,也不太友好;
解決:可以使用單獨一個類來管理創建這些類,然後提供方法出來,下面列舉.


public class IfElse031 {

    public ShareItem createLinkShareItem(String link,String title,String content) {
            return new IfElse03.Link(link,title,content);
        }

    public ShareItem createImageShareItem(String imagePath) {
            return new IfElse03.Image(imagePath); 
        }

    public ShareItem createTextShareItem(String content) { 
            return new IfElse03.Text(content); 
        }

    public ShareItem createImageTextShareItem(String imagePath, String content) { 
            return new IfElse03.ImageText(imagePath,content);
        }


}

4.就類似於上面這麼解決,單獨的一個類來管理這些子類,從而方便開發者進行調用。 另外,也可以單獨提供type的形式來調用這些類,那麼就得用map來進行type和子類的對應,所以:


/**
 * 作用:常量類,用於提供常量
 */
public class Constant {

        public static final int TYPE_LINK = 0;
        public static final int TYPE_TEXT = 1;
        public static final int TYPE_IMAGE = 2;
        public static final int TYPE_IMAGE_TEXT = 3;
}

public abstract class ShareItem {

        int type;
        //List<String> args;
        public ShareItem(int type) { 
            this.type = type;
        }
        public ShareItem() {
        } 
        public void isCanShare(ShareListener listener) {
            if(listener == null){
                return;
            }
            doShare(listener);
        }
        abstract void doShare(ShareListener listener);
        /*public void setList(List args) {
            this.args = args;
        }*/
}

public class Link extends ShareItem {

        String mLink;
        String mTitle;
        String mContent;
        public Link() { 

}
public Link(String link,String title,String content) {
            super(Constant.TYPE_LINK);
            this.mLink = (link !=null && link !="")? link : "default";
            this.mTitle = (link != null && link != "")? link : "default";
            this.mContent = (link != null && link != "")? link : "default";
}
    @Override
    public void doShare(ShareListener listener) {
            //TODO
    }

}

public class Text extends ShareItem {

        String content;
        public Text() {

        }
        public Text(String content){
            super(Constant.TYPE_TEXT);
            this.content = (content != null && content != "")? content : "default";
        }
        @Override
        public void doShare(ShareListener listener) { 
            //TODO
        }
}


    public class Image extends ShareItem {

        String imagePath;

        public Image() {
        }
        public Image(String imagePath) {
            super(Constant.TYPE_IMAGE);
            this.imagePath = (imagePath != null && imagePath != "")? imagePath : "default";
        }
        @Override
        public void doShare(ShareListener listener) { 
            //TODO
        }

}


public class ImageText extends ShareItem {

        public String imagePath;
        public String content;

        public ImageText(String imagePath, String content){
            super(Constant.TYPE_IMAGE_TEXT);
            this.imagePath = (imagePath != null && imagePath != "")? imagePath : "default";
            this.content = (content != null && content != "")? content : "default";
        }
        public ImageText() {

        }

    @Override
    public void doShare(ShareListener listener) { 

            if(listener == null) {
                return;
            }
            if(imagePath == "default" || content == "default") { 
                listener.onCallback(ShareListener.STATE_FAIL, "分享信息不完整"); 
                return;
            }
            listener.onCallback(ShareListener.STATE_SUCC, "鏈接 分享成功4 : IMAGE_PATH=" + imagePath + ",CONTENT=" + content); 
        }
}

/**異常處理*/
public class DefaultShareItem extends ShareItem {

        public DefaultShareItem() {
            super(-1); 
            System.out.println("捕獲到了異常"); 
        }

        @Override
        void doShare(ShareListener listener) {
            //TODO
        }
}

/**提供給開發調用的類*/
public class Demo01 {

    private Map<Integer,Class<? extends ShareItem>> shareMaps = new HashMap<Integer,Class<? extends ShareItem>>();
    private void init() {
        shareMaps.put(IfElse04.TYPE_LINK, Link.class);
        shareMaps.put(IfElse04.TYPE_TEXT, Text.class);
        shareMaps.put(IfElse04.TYPE_IMAGE, Image.class);
        shareMaps.put(IfElse04.TYPE_IMAGE_TEXT, ImageText.class);
        shareMaps.put(IfElse04.TYPE_LINK, Link.class);
    }

    public ShareItem createShareItem(int type){
        if(shareMaps.size() == 0) {
            init();
        }
        try {
        Class<? extends ShareItem> cls = shareMaps.get(type);
        return cls.newInstance(); 
        }catch (IllegalAccessException e) {
            //e.printStackTrace();
            System.out.println("IllegalAccessException");
            return new DefaultShareItem();
        }catch (InstantiationException e) {
            //e.printStackTrace();
            System.out.println("InstantiationException");
            return new DefaultShareItem();
        } 
    }
}

上面每種方法都各有優缺點,用map來存儲type和操作類的形式,雖不用維護多個類,也使得多個類不用對外開放,但是卻還得設置各個類應有的參數(這個在上面未實現),設置參數的方法可以寫在ShareItem抽象類,也可以寫在子類(調用的時候得將基類強轉爲對應子類)。

個人覺得還是上面第三種比較好用,使用多態來控制多個類,從而避免if-else,再另外單獨的類來管理這些子類,從而方便開發者進行調用

下面這個是Main類,主要調用上面的各個方法進行測試

/**
 * 作用:測試IF優化的主類
 */
public class Main {

        public static void main(String[] args) {
                //test1();
                //test2();
                //test3();
                test4();
        }

        public static void test1() {
                //第一種情況(原始的if-else嵌套)
                //IfElse01.ShareItem item = new IfElse01.ShareItem();
                ShareItem item = IfElse01.createShareItem(); 
                ShareListener listener = new ShareListener() {
                    @Override
                    public void onCallback(int state, String msg) {
                        //TODO
                        System.out.println("state : " + state + ", msg : " + msg); 
                    }
                };
                IfElse01.share(item,listener);
        }

        public static void test2() {
                //第二種情況(內外接口的方式來減少if-else)
                ShareItem item = IfElse01.createShareItem(); 
                ShareListener listener = new ShareListener() {
                    @Override
                    public void onCallback(int state, String msg) {
                        //TODO
                        System.out.println("state : " + state + ", msg : " + msg); 
                    }
                };
                IfElse02 ifElse02 = new IfElse02();
                ifElse02.share(item, listener); 
        }

        public static void test3() {
                //第三種情況(多態,缺點:多個類對外開放,可以單獨一個類來提供這些類,然後提供方法出來讓使用者獲取)
                ShareListener listener = new ShareListener() {
                    @Override
                    public void onCallback(int state, String msg) {
                        //TODO
                        System.out.println("state : " + state + ", msg : " + msg); 
                    }
                };
                /*IfElse03 ifElse03 = new IfElse03();
                IfElse03.ShareItem item1 = new IfElse03.Link("http://www.baidu.com","標題","內容");
                ifElse03.share(item1, listener);*/
                IfElse031 ifElse031 = new IfElse031();  
                com.wyk.ifelse.sdk.IfElse03.ShareItem linkShareItem = ifElse031.createLinkShareItem("http://www.baidu.com","標題","內容");
                linkShareItem.doShare(listener);
            }

        public static void test4() { 
                //第四種情況(封裝成SDK的形式 + 使用map來維護多個類),缺點,
                ShareListener listener = new ShareListener() {
                    @Override
                    public void onCallback(int state, String msg) {
                        //TODO
                        System.out.println("state : " + state + ", msg : " + msg); 
                    }
                };
                ///////////////////////////////////////////////////////////////////////////
                /*IfElse041 ifElse041 = new IfElse041();
                //ifElse041.doShare(IfElse04.TYPE_IMAGE_TEXT, listener);
                com.wyk.ifelse.sdk.IfElse04.ShareItem shareItem = ifElse041.createShareItem(IfElse04.TYPE_IMAGE_TEXT);
                shareItem.isCanShare(listener);*/
                /////////////////////////////////////////////////////////////////////////

                Demo01 demo01 = new Demo01();
                com.wyk.ifelse.sdk.test.ShareItem shareItem1 = demo01.createShareItem(Constant.TYPE_IMAGE_TEXT); 
                /**設置參數 方法1,缺點:還得用戶熟悉設置參數的步驟*/
                /*String[] args = new String[]{"http://www.sohu.com","內容"}; 
                shareItem1.setList(Arrays.asList(args));*/
                /**設置參數 方法2, 缺點:不人性化,還得用戶轉*/
                ImageText imageText = (ImageText)shareItem1;
                imageText.imagePath = "http://www.kugou.com";
                imageText.content = "內容";
                imageText.isCanShare(listener);

            }
}

Ⅲ.總結

微信的分享、友盟的集成分享也是基於上面第三種方式和第四種方式,各有好處吧~ 看看SDK封裝代碼,可以減少代碼的維護成本,從而提高代碼的質量. 感謝簡書該作者的分享.

上面的代碼地址: https://github.com/XK-one/IfTest
聲明:如有侵權,請告知刪除.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章