资讯专栏INFORMATION COLUMN

如何避免if else

YancyYe / 744人阅读

摘要:在开发的过程中相信你也会写很多的语句吧,此篇主要来讲讲如何在日常开发的过程中尽量少的使用语句。策略一单例模式这种单例模式在类一加载的时候就将单例对象创建完毕,总是这个对象存在内存中,避免了通过线程同步来生成对象,线程安全的创建方式。

在开发的过程中相信你也会写很多的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 Map strategyInfoMap = 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 Map strategyInfoMap = 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 Map strategyInfoMap = 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

相关文章

  • 谈谈代码——如何避免写出糟糕if...else语句

    摘要:源码剖析之设计模式鉴赏策略模式小结在这篇文章中笔者和大家分享几个减少的小由于这些都会有一定的限制因此还向大家介绍了几个能够避免写出糟糕的的设计模式并使用观察者模式简单的改进了仲裁者模式的例子 本文首发于数据浮云:https://mp.weixin.qq.com/s?__... 在写代码的日常中,if...else语句是极为常见的.正因其常见性,很多同学在写代码的时候并不会去思考其在目...

    huhud 评论0 收藏0
  • 活用设计模式:如何避免一连串的if else

    摘要:对之前来说,没有一等函数,就要把每个条件判断写成接口的实现类。需要前后链接,节点对其后的子链有控制力,所以不那么像。 另载于 http://www.qingjingjie.com/blogs/8 前段时间知乎上有人发了这么个段子: 某日,老师在课堂上想考考学生们的智商,就问一个男孩: 树上有十只鸟,开枪打死一只,还剩几只? 男孩反问:是无声手枪,还是其他没有声音的枪么? 不是. ...

    yanbingyun1990 评论0 收藏0
  • 在微信小程序中绘制图表(part2)

    摘要:本期大纲确定纵坐标的范围并绘制根据真实数据绘制折线相关阅读在微信小程序中绘制图表在微信小程序中绘制图表关注我的项目查看完整代码。相关阅读在微信小程序中绘制图表在微信小程序中绘制图表 本期大纲 1、确定纵坐标的范围并绘制 2、根据真实数据绘制折线 相关阅读:在微信小程序中绘制图表(part1)在微信小程序中绘制图表(part3) 关注我的 github 项目 查看完整代码。 确定纵坐...

    canopus4u 评论0 收藏0
  • 编写扁平化的代码

    摘要:原文作者给你的代码增加一点点函数式编程的特性最近我对函数式编程非常感兴趣。对我而言,函数式编程最大的作用就是强制你编写声明性代码代码描述你做什么,而不是在描述如何做。事实证明,编写声明式代码是函数式编程中最简单的部分之一。 原文:Writing flat & declarative code作者:Peeke Kuepers -- 给你的代码增加一点点函数式编程的特性 最近我对函数式编程...

    lunaticf 评论0 收藏0

发表评论

0条评论

YancyYe

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<