摘要:在開發(fā)的過程中相信你也會寫很多的語句吧,此篇主要來講講如何在日常開發(fā)的過程中盡量少的使用語句。策略一單例模式這種單例模式在類一加載的時(shí)候就將單例對象創(chuàng)建完畢,總是這個對象存在內(nèi)存中,避免了通過線程同步來生成對象,線程安全的創(chuàng)建方式。
在開發(fā)的過程中相信你也會寫很多的if else語句吧,此篇主要來講講如何在日常開發(fā)的過程中盡量少的使用if else語句。
0x01 為什么要去if else在開發(fā)的過程中我們可能會經(jīng)常遇到if else的邏輯,寫很多if else對于一位有情懷的程序員看來是不可以接收的,也影響閱讀人的閱讀感受,同時(shí)程序也違背了對修改關(guān)閉擴(kuò)展開放的原則。在寫程序的過程中我們應(yīng)該盡量保證修改關(guān)閉,也就是說自己的寫的代碼邏輯應(yīng)不該讓別人在擴(kuò)展邏輯的過程中進(jìn)行修改,同時(shí)保證高的可擴(kuò)展性。
在使用if else寫程序的過程中你可能會寫出如下的代碼:
String strategy = ""; if(strategy.equals("策略一")){ }else if(strategy.equals("策略二")){ }else if(...){ }else { }
當(dāng)需要加一個分支邏輯就必須得去if else結(jié)構(gòu)中改代碼,這樣不利于程序擴(kuò)展,同時(shí)也非常難維護(hù),如果業(yè)務(wù)復(fù)雜到一定的程度這塊代碼可能沒法去重構(gòu)了。
0x02 策略模式 + 工廠模式 + 單例模式在想到要去掉if else這種結(jié)構(gòu)來寫代碼,首先容易想到的是通過一個map來保存key對應(yīng)的邏輯,作為一個從c++轉(zhuǎn)到j(luò)ava開發(fā)的程序的思維是通過函數(shù)指針來解決問題,但是java并沒有這么個東西,所以就有了下面這段代碼邏輯了。
public class StrategyTest { public static void main(String[] args) { String result = ObtainStrategyInfo.getInstance().getStrategyInfo("策略一"); System.out.println(result); } } /* (單例模式) */ class ObtainStrategyInfo { private static final ObtainStrategyInfo obtainStrategyInfo = new ObtainStrategyInfo(); public static ObtainStrategyInfo getInstance(){ return obtainStrategyInfo; } public String getStrategyInfo(String strategy){ StrategyInfo strategyInfo = new StrategyFactory().getStrategyInfoClass(strategy); return strategyInfo.getStrategyInfo(strategy); } } 這種單例模式在類一加載的時(shí)候就將單例對象創(chuàng)建完畢,總是這個對象存在內(nèi)存中,避免了通過線程同步來生成對象,線程安全的創(chuàng)建方式。 /* 其實(shí)最終的if else判斷邏輯都在這里了 (工廠模式)*/ class StrategyFactory { private static MapstrategyInfoMap = new HashMap (); static { strategyInfoMap.put("策略一", new Strategy1()); strategyInfoMap.put("策略二", new Strategy2()); } public StrategyInfo getStrategyInfoClass(String strategy){ StrategyInfo strategyInfo = null; for(String key : strategyInfoMap.keySet()){ if(strategy.equals(key)) { strategyInfo = strategyInfoMap.get(key); } } return strategyInfo; } } /* (策略模式) */ interface StrategyInfo { String getStrategyInfo(String strategy); } class Strategy1 implements StrategyInfo { public String getStrategyInfo(String strategy) { return strategy; } } class Strategy2 implements StrategyInfo { public String getStrategyInfo(String strategy) { return strategy; } }
如果需要擴(kuò)展策略三,是不是只要添加自己的邏輯代碼就行了呢?保證對修改關(guān)閉?答案是肯定的。可以如下方式來擴(kuò)展策略三:
/* 在StrategyFactory中注入策略三的對應(yīng)關(guān)系 */ strategyInfoMap.put("策略三", new Strategy3()); /* 然后定義策略三 */ class Strategy3 implements StrategyInfo { public String getStrategyInfo(String strategy) { return strategy; } }
這樣可非常方便的擴(kuò)展策略四、策略五。
0x03 優(yōu)化版(策略模式 + 工廠模式 + 單例模式)上面講到的(策略模式 + 工廠模式 + 單例模式)來去if else的實(shí)現(xiàn)方式,還是存在一些微小的問題,還是需要手動去工廠中去注冊新增加的策略,本版塊結(jié)合spring bean的生命周期做到后續(xù)擴(kuò)展只需要增加自己的策略就行,策略類在被spring實(shí)例化得生命周期中實(shí)現(xiàn)向工廠中注冊自己。
public class StrategyTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/config/applicationContext.xml"); String result = ObtainStrategyInfo.getInstance().getStrategyInfo("策略一"); System.out.println(result); } } class ObtainStrategyInfo { private static final ObtainStrategyInfo obtainStrategyInfo = new ObtainStrategyInfo(); private StrategyFactory strategyFactory = new StrategyFactory(); public static ObtainStrategyInfo getInstance(){ return obtainStrategyInfo; } public String getStrategyInfo(String strategy){ StrategyInfo strategyInfo = strategyFactory.getStrategyInfoClass(strategy); return strategyInfo.getStrategyInfo(strategy); } } class StrategyFactory { private static MapstrategyInfoMap = new HashMap (); public StrategyInfo getStrategyInfoClass(String strategy){ return strategyInfoMap.get(strategy); } /* 被策略調(diào)用實(shí)現(xiàn)自動注冊 */ public static void addStrategyForFactory(String strategyName, StrategyInfo strategyInfo) { strategyInfoMap.put(strategyName, strategyInfo); } } interface StrategyInfo { String getStrategyInfo(String strategy); } class Strategy1 implements StrategyInfo, InitializingBean { private static final String identify = "策略一"; public String getStrategyInfo(String strategy) { return "策略一 " + strategy; } /* Strategy2的對象在初始化完成后會調(diào)用這個生命周期函數(shù) */ public void afterPropertiesSet() throws Exception { StrategyFactory.addStrategyForFactory(identify, this); } } class Strategy2 implements StrategyInfo, InitializingBean { private static final String identify = "策略一"; public String getStrategyInfo(String strategy) { return "策略二 " + strategy; } public void afterPropertiesSet() throws Exception { StrategyFactory.addStrategyForFactory(identify, this); } }
后面再對策略進(jìn)行新增的時(shí)候只需要都實(shí)現(xiàn)InitializingBean這個接口的afterPropertiesSet方法就再自己實(shí)例化后向StrategyFactory中注冊自己,極大的降低了擴(kuò)展成本。
0x04 spring應(yīng)用上下文 + spring bean生命周期spring bean的生命周期是個很好被利用的技巧,這里我們又利用了sping應(yīng)用上下文和bean的生命周期繼續(xù)重構(gòu)上面的實(shí)現(xiàn)方式。
public class StrategyTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/config/applicationContext.xml"); StrategyLoader strategyLoader = applicationContext.getBean(StrategyLoader.class); String result = strategyLoader.getStrategyInfo("策略一"); System.out.println(result); } } class StrategyLoader implements InitializingBean, ApplicationContextAware{ private ApplicationContext applicationContext; private static MapstrategyInfoMap = new HashMap (); public void afterPropertiesSet() throws Exception { Map strategyInfos = applicationContext.getBeansOfType(StrategyInfo.class); if(CollectionUtils.isEmpty(strategyInfos)) { return; } for(String key : strategyInfos.keySet()) { strategyInfoMap.put(strategyInfos.get(key).getIdentify(), strategyInfos.get(key)); } } public String getStrategyInfo(String strategy){ StrategyInfo strategyInfo = strategyInfoMap.get(strategy); if(strategyInfo != null) { return strategyInfo.getStrategyInfo(strategy); } return ""; } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } } interface StrategyInfo { String getStrategyInfo(String strategy); String getIdentify(); } class Strategy1 implements StrategyInfo { private static final String identify = "策略一"; public String getStrategyInfo(String strategy) { return "策略一 " + strategy; } public String getIdentify(){ return identify; } } class Strategy2 implements StrategyInfo { private static final String identify = "策略一"; public String getStrategyInfo(String strategy) { return "策略二 " + strategy; } public String getIdentify(){ return identify; } }
這是我們擴(kuò)展策略就更加簡單方便了,我們只需要正常的實(shí)現(xiàn)StrategyInfo接口,以實(shí)現(xiàn)動態(tài)擴(kuò)展。
0x05 后記后面如果遇到好的去掉if else方式會追加到這里。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/64894.html
摘要:源碼剖析之設(shè)計(jì)模式鑒賞策略模式小結(jié)在這篇文章中筆者和大家分享幾個減少的小由于這些都會有一定的限制因此還向大家介紹了幾個能夠避免寫出糟糕的的設(shè)計(jì)模式并使用觀察者模式簡單的改進(jìn)了仲裁者模式的例子 本文首發(fā)于數(shù)據(jù)浮云:https://mp.weixin.qq.com/s?__... 在寫代碼的日常中,if...else語句是極為常見的.正因其常見性,很多同學(xué)在寫代碼的時(shí)候并不會去思考其在目...
摘要:對之前來說,沒有一等函數(shù),就要把每個條件判斷寫成接口的實(shí)現(xiàn)類。需要前后鏈接,節(jié)點(diǎn)對其后的子鏈有控制力,所以不那么像。 另載于 http://www.qingjingjie.com/blogs/8 前段時(shí)間知乎上有人發(fā)了這么個段子: 某日,老師在課堂上想考考學(xué)生們的智商,就問一個男孩: 樹上有十只鳥,開槍打死一只,還剩幾只? 男孩反問:是無聲手槍,還是其他沒有聲音的槍么? 不是. ...
摘要:本期大綱確定縱坐標(biāo)的范圍并繪制根據(jù)真實(shí)數(shù)據(jù)繪制折線相關(guān)閱讀在微信小程序中繪制圖表在微信小程序中繪制圖表關(guān)注我的項(xiàng)目查看完整代碼。相關(guān)閱讀在微信小程序中繪制圖表在微信小程序中繪制圖表 本期大綱 1、確定縱坐標(biāo)的范圍并繪制 2、根據(jù)真實(shí)數(shù)據(jù)繪制折線 相關(guān)閱讀:在微信小程序中繪制圖表(part1)在微信小程序中繪制圖表(part3) 關(guān)注我的 github 項(xiàng)目 查看完整代碼。 確定縱坐...
閱讀 1206·2021-11-08 13:13
閱讀 1790·2019-08-30 15:55
閱讀 2869·2019-08-29 11:26
閱讀 2508·2019-08-26 13:56
閱讀 2639·2019-08-26 12:15
閱讀 2212·2019-08-26 11:41
閱讀 1478·2019-08-26 11:00
閱讀 1600·2019-08-23 18:30