摘要:在开发的过程中相信你也会写很多的语句吧,此篇主要来讲讲如何在日常开发的过程中尽量少的使用语句。策略一单例模式这种单例模式在类一加载的时候就将单例对象创建完毕,总是这个对象存在内存中,避免了通过线程同步来生成对象,线程安全的创建方式。
在开发的过程中相信你也会写很多的if else语句吧,此篇主要来讲讲如何在日常开发的过程中尽量少的使用if else语句。
0x01 为什么要去if else在开发的过程中我们可能会经常遇到if else的逻辑,写很多if else对于一位有情怀的程序员看来是不可以接收的,也影响阅读人的阅读感受,同时程序也违背了对修改关闭扩展开放的原则。在写程序的过程中我们应该尽量保证修改关闭,也就是说自己的写的代码逻辑应不该让别人在扩展逻辑的过程中进行修改,同时保证高的可扩展性。
在使用if else写程序的过程中你可能会写出如下的代码:
String strategy = ""; if(strategy.equals("策略一")){ }else if(strategy.equals("策略二")){ }else if(...){ }else { }
当需要加一个分支逻辑就必须得去if else结构中改代码,这样不利于程序扩展,同时也非常难维护,如果业务复杂到一定的程度这块代码可能没法去重构了。
0x02 策略模式 + 工厂模式 + 单例模式在想到要去掉if else这种结构来写代码,首先容易想到的是通过一个map来保存key对应的逻辑,作为一个从c++转到java开发的程序的思维是通过函数指针来解决问题,但是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); } } 这种单例模式在类一加载的时候就将单例对象创建完毕,总是这个对象存在内存中,避免了通过线程同步来生成对象,线程安全的创建方式。 /* 其实最终的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; } }
如果需要扩展策略三,是不是只要添加自己的逻辑代码就行了呢?保证对修改关闭?答案是肯定的。可以如下方式来扩展策略三:
/* 在StrategyFactory中注入策略三的对应关系 */ strategyInfoMap.put("策略三", new Strategy3()); /* 然后定义策略三 */ class Strategy3 implements StrategyInfo { public String getStrategyInfo(String strategy) { return strategy; } }
这样可非常方便的扩展策略四、策略五。
0x03 优化版(策略模式 + 工厂模式 + 单例模式)上面讲到的(策略模式 + 工厂模式 + 单例模式)来去if else的实现方式,还是存在一些微小的问题,还是需要手动去工厂中去注册新增加的策略,本版块结合spring bean的生命周期做到后续扩展只需要增加自己的策略就行,策略类在被spring实例化得生命周期中实现向工厂中注册自己。
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); } /* 被策略调用实现自动注册 */ 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的对象在初始化完成后会调用这个生命周期函数 */ 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); } }
后面再对策略进行新增的时候只需要都实现InitializingBean这个接口的afterPropertiesSet方法就再自己实例化后向StrategyFactory中注册自己,极大的降低了扩展成本。
0x04 spring应用上下文 + spring bean生命周期spring bean的生命周期是个很好被利用的技巧,这里我们又利用了sping应用上下文和bean的生命周期继续重构上面的实现方式。
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; } }
这是我们扩展策略就更加简单方便了,我们只需要正常的实现StrategyInfo接口,以实现动态扩展。
0x05 后记后面如果遇到好的去掉if else方式会追加到这里。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64894.html
摘要:源码剖析之设计模式鉴赏策略模式小结在这篇文章中笔者和大家分享几个减少的小由于这些都会有一定的限制因此还向大家介绍了几个能够避免写出糟糕的的设计模式并使用观察者模式简单的改进了仲裁者模式的例子 本文首发于数据浮云:https://mp.weixin.qq.com/s?__... 在写代码的日常中,if...else语句是极为常见的.正因其常见性,很多同学在写代码的时候并不会去思考其在目...
摘要:对之前来说,没有一等函数,就要把每个条件判断写成接口的实现类。需要前后链接,节点对其后的子链有控制力,所以不那么像。 另载于 http://www.qingjingjie.com/blogs/8 前段时间知乎上有人发了这么个段子: 某日,老师在课堂上想考考学生们的智商,就问一个男孩: 树上有十只鸟,开枪打死一只,还剩几只? 男孩反问:是无声手枪,还是其他没有声音的枪么? 不是. ...
摘要:本期大纲确定纵坐标的范围并绘制根据真实数据绘制折线相关阅读在微信小程序中绘制图表在微信小程序中绘制图表关注我的项目查看完整代码。相关阅读在微信小程序中绘制图表在微信小程序中绘制图表 本期大纲 1、确定纵坐标的范围并绘制 2、根据真实数据绘制折线 相关阅读:在微信小程序中绘制图表(part1)在微信小程序中绘制图表(part3) 关注我的 github 项目 查看完整代码。 确定纵坐...
阅读 1103·2021-11-08 13:13
阅读 1688·2019-08-30 15:55
阅读 2725·2019-08-29 11:26
阅读 2410·2019-08-26 13:56
阅读 2524·2019-08-26 12:15
阅读 2093·2019-08-26 11:41
阅读 1373·2019-08-26 11:00
阅读 1514·2019-08-23 18:30