策略模式——消除大量if-else,並支援動態增加
今天百度面試,先問了一個專案點
我對於小米、魅族、Android6.0以上機型的適配
需要進行大量判斷
面試官真的很厲害,問我能不能用設計模式改進這個大量的判斷,如果後期想要新增條件,如何來的方便?
if(sdk>6.0) {
action1();
} else if(sdk>4.4) {
if(小米) {
action2();
} else if (魅族) {
action3();
}
}
其實工廠、設計模式這一塊我 好久不看了,當時就想到寫一個抽象 操作類
public abstract class AbstractAdapter {
abstract void doAdapter();
}
小米適配類
public class XiaoMiAdapter extends AbstractAdapter {
void doAdapter() {
do1;
}
}
以此類推。。。
所以現在是
AbstractAdapter adapter = null; if(sdk>6.0) { adapter = new SixAdapter(); } else if(sdk>4.4) { if(小米) { adapter = XiaoMiAdapter(); } else if (魅族) { adapter = MeiZuAdapter(); } } if (adapter != null) { adapter.doAdapter(); }
現在當你需要新增一個機型,比如 華為,只需要建立HuaWeiAdapter繼承自抽象A dapter就可以了。然後 增加一個條件,再例項化一個華為介面卡即可。呼叫還是下面的統一呼叫方式。
事後回到住處,我又想了想如何優化。
我抽象了一下,只留下了條件
小米適配條件:6.0>sdk>4.4,小米
魅族適配條件:6.0>sdk>4.4,魅族
6.0以上適配條件:sdk>6.0,任意機型
現在有3個條件物件,如果我現在手機的引數,去遍歷這3 個條件物件,那不是就可以了?
所以抽象出一個抽象條件類,AbstractCondition。繼承3個。
abstract class AbstractCondition { abstract boolean isMatchCondition(int sdk, MobilePhone mobilePhone); } class XiaoMiCondition extends AbstractCondition{ @Override boolean isMatchCondition(int sdk, MobilePhone mobilePhone) { return mobilePhone == "小米" && (sdk < 6.0 || sdk > 4.4); } } }
嘿嘿,把他們都放 集合裡去
List<AbstractCondition> conditionList = new ArrayList<>();
conditionList.add(new XiaoMiCondition());
conditionList.add(new MeiZuCondition());
conditionList.add(new SixCondition());
寫到一半發現不夠,於是新增了一個方法
abstract class AbstractCondition {
abstract boolean isMatchCondition(int sdk, MobilePhone mobilePhone);
abstract String getMobilePhoneTag();
}
class XiaoMiCondition extends AbstractCondition{
@Override
boolean isMatchCondition(int sdk, MobilePhone mobilePhone) {
return mobilePhone == "小米" && (sdk < 6.0 || sdk > 4.4);
}
@Override
String getMobilePhoneTag() {
return "小米";
}
}
遍歷集合,找到符合的條件
private String findMatchedCondition(int sdk, MobilePhone mobilePhone) {
for (AbstractCondition condition : conditionList) {
if (condition.isMatchCondition(sdk, mobilePhone)) {
return condition.getMobilePhoneTag();
}
}
return null;
}
再根據tag找到對應的介面卡。
流程大致是這樣的:遍歷條件集合, 找到匹配條件,取得tag。tag相當於是這個條件了。這個條件又會對應一個介面卡。所以我們又會用這個tag去找到對應的介面卡。然後進行適配。以後再也不用修改if-else了,只需要新建 條件類和處理類 就可以了。
也可以簡化一下,把條件類和處理類放在一起。最後給一個完整的優化後的demo吧!
抽象類
public abstract class AbstractAdapter {
public abstract void adapter(int sdk, String mobilePhoneType);
}
以小米的繼承 為例
public class XiaoMiAdapter extends AbstractAdapter{
@Override
public void adapter(int sdk, String mobilePhoneType) {
if (sdk < 6.0 && sdk > 4.4 && mobilePhoneType.equals("小米")) {
//執行小米的適配工作
}
}
}
適配中心
public class AdapterCenter {
private List<AbstractAdapter> adapterList;
AdapterCenter() {
adapterList = new ArrayList<>();
adapterList.add(new XiaoMiAdapter());
adapterList.add(new MeiZuAdapter());
adapterList.add(new SixAdapter());
}
public void adapter(int sdk, String mobilePhoneType) {
for (AbstractAdapter adapter : adapterList) {
adapter.adapter(sdk, mobilePhoneType);
}
}
}
外部呼叫,舒服死了誒
AdapterCenter adapterCenter = new AdapterCenter();
adapterCenter.adapter(5, "小米");
再也 沒有海量if-else了
除此之外。下次想要新增華為適配,誒喲,舒服上天了誒!
新增華為介面卡
public class HuaWeiAdapter extends AbstractAdapter{
@Override
public void adapter(int sdk, String mobilePhoneType) {
if (sdk == 5 && mobilePhoneType.equals("華為")) {
//進行華為適配
}
}
}
在介面卡中心註冊一下
adapterList.add(new HuaWeiAdapter());
以後再也不怕if-else啦。。。。。。。。
我要感謝這個面試官,讓我的程式碼水平上升了,mua~~~
---
今日又想了下,如何匹配到一個,並進行了適配後,不再繼續向下遍歷呢?
果斷想到,這裡的Okhttp型的責任鏈是最好的解決形式