Ⅰ.前言
前些天在簡書上看了 “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
聲明:如有侵權,請告知刪除.