摘要:在開發(fā)的過程中相信你也會(huì)寫很多的語句吧,此篇主要來講講如何在日常開發(fā)的過程中盡量少的使用語句。策略一單例模式這種單例模式在類一加載的時(shí)候就將單例對(duì)象創(chuàng)建完畢,總是這個(gè)對(duì)象存在內(nèi)存中,避免了通過線程同步來生成對(duì)象,線程安全的創(chuàng)建方式。
在開發(fā)的過程中相信你也會(huì)寫很多的if else語句吧,此篇主要來講講如何在日常開發(fā)的過程中盡量少的使用if else語句。
0x01 為什么要去if else在開發(fā)的過程中我們可能會(huì)經(jīng)常遇到if else的邏輯,寫很多if else對(duì)于一位有情懷的程序員看來是不可以接收的,也影響閱讀人的閱讀感受,同時(shí)程序也違背了對(duì)修改關(guān)閉擴(kuò)展開放的原則。在寫程序的過程中我們應(yīng)該盡量保證修改關(guān)閉,也就是說自己的寫的代碼邏輯應(yīng)不該讓別人在擴(kuò)展邏輯的過程中進(jìn)行修改,同時(shí)保證高的可擴(kuò)展性。
在使用if else寫程序的過程中你可能會(huì)寫出如下的代碼:
String strategy = ""; if(strategy.equals("策略一")){ }else if(strategy.equals("策略二")){ }else if(...){ }else { }
當(dāng)需要加一個(gè)分支邏輯就必須得去if else結(jié)構(gòu)中改代碼,這樣不利于程序擴(kuò)展,同時(shí)也非常難維護(hù),如果業(yè)務(wù)復(fù)雜到一定的程度這塊代碼可能沒法去重構(gòu)了。
0x02 策略模式 + 工廠模式 + 單例模式在想到要去掉if else這種結(jié)構(gòu)來寫代碼,首先容易想到的是通過一個(gè)map來保存key對(duì)應(yīng)的邏輯,作為一個(gè)從c++轉(zhuǎn)到j(luò)ava開發(fā)的程序的思維是通過函數(shù)指針來解決問題,但是java并沒有這么個(gè)東西,所以就有了下面這段代碼邏輯了。
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í)候就將單例對(duì)象創(chuàng)建完畢,總是這個(gè)對(duì)象存在內(nèi)存中,避免了通過線程同步來生成對(duì)象,線程安全的創(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ò)展策略三,是不是只要添加自己的邏輯代碼就行了呢?保證對(duì)修改關(guān)閉?答案是肯定的。可以如下方式來擴(kuò)展策略三:
/* 在StrategyFactory中注入策略三的對(duì)應(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)方式,還是存在一些微小的問題,還是需要手動(dòng)去工廠中去注冊(cè)新增加的策略,本版塊結(jié)合spring bean的生命周期做到后續(xù)擴(kuò)展只需要增加自己的策略就行,策略類在被spring實(shí)例化得生命周期中實(shí)現(xiàn)向工廠中注冊(cè)自己。
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)自動(dòng)注冊(cè) */ 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的對(duì)象在初始化完成后會(huì)調(diào)用這個(gè)生命周期函數(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); } }
后面再對(duì)策略進(jìn)行新增的時(shí)候只需要都實(shí)現(xiàn)InitializingBean這個(gè)接口的afterPropertiesSet方法就再自己實(shí)例化后向StrategyFactory中注冊(cè)自己,極大的降低了擴(kuò)展成本。
0x04 spring應(yīng)用上下文 + spring bean生命周期spring bean的生命周期是個(gè)很好被利用的技巧,這里我們又利用了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)動(dòng)態(tài)擴(kuò)展。
0x05 后記后面如果遇到好的去掉if else方式會(huì)追加到這里。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/64894.html
摘要:源碼剖析之設(shè)計(jì)模式鑒賞策略模式小結(jié)在這篇文章中筆者和大家分享幾個(gè)減少的小由于這些都會(huì)有一定的限制因此還向大家介紹了幾個(gè)能夠避免寫出糟糕的的設(shè)計(jì)模式并使用觀察者模式簡單的改進(jìn)了仲裁者模式的例子 本文首發(fā)于數(shù)據(jù)浮云:https://mp.weixin.qq.com/s?__... 在寫代碼的日常中,if...else語句是極為常見的.正因其常見性,很多同學(xué)在寫代碼的時(shí)候并不會(huì)去思考其在目...
摘要:對(duì)之前來說,沒有一等函數(shù),就要把每個(gè)條件判斷寫成接口的實(shí)現(xiàn)類。需要前后鏈接,節(jié)點(diǎn)對(duì)其后的子鏈有控制力,所以不那么像。 另載于 http://www.qingjingjie.com/blogs/8 前段時(shí)間知乎上有人發(fā)了這么個(gè)段子: 某日,老師在課堂上想考考學(xué)生們的智商,就問一個(gè)男孩: 樹上有十只鳥,開槍打死一只,還剩幾只? 男孩反問:是無聲手槍,還是其他沒有聲音的槍么? 不是. ...
摘要:本期大綱確定縱坐標(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)目 查看完整代碼。 確定縱坐...
摘要:原文作者給你的代碼增加一點(diǎn)點(diǎn)函數(shù)式編程的特性最近我對(duì)函數(shù)式編程非常感興趣。對(duì)我而言,函數(shù)式編程最大的作用就是強(qiáng)制你編寫聲明性代碼代碼描述你做什么,而不是在描述如何做。事實(shí)證明,編寫聲明式代碼是函數(shù)式編程中最簡單的部分之一。 原文:Writing flat & declarative code作者:Peeke Kuepers -- 給你的代碼增加一點(diǎn)點(diǎn)函數(shù)式編程的特性 最近我對(duì)函數(shù)式編程...
閱讀 1123·2021-11-08 13:13
閱讀 1707·2019-08-30 15:55
閱讀 2762·2019-08-29 11:26
閱讀 2427·2019-08-26 13:56
閱讀 2549·2019-08-26 12:15
閱讀 2125·2019-08-26 11:41
閱讀 1394·2019-08-26 11:00
閱讀 1530·2019-08-23 18:30