小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了

栏目: IT技术 · 发布时间: 6年前

内容简介:这里涉及到一个关键词:策略模式,那么到底什么是策略模式呢?本文就来好好给大家讲讲策略模式,大家可以带着如下几个问题来阅读本文:1. 如何通过策略模式优化业务逻辑代码(可以根据自己从事的工作思考)2. 使用策略模式优化if-else,会不会带来什么副作用呢?

这里涉及到一个关键词:策略模式,那么到底什么是策略模式呢?本文就来好好给大家讲讲策略模式,大家可以带着如下几个问题来阅读本文:

1. 如何通过策略模式优化业务逻辑代码(可以根据自己从事的工作思考)

2. 使用策略模式优化if-else,会不会带来什么副作用呢?

3. 实现策略模式是否有更好的方式呢?

1. 策略模式如何优化代码解构

要会带这个问题,需要先弄清楚策略模式的定义,首先来看策略模式的教科书定义:策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。 策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。 策略模式是一种对象行为型模式。

这里的算法其实就是业务逻辑,为了更形象,干脆将其理解为一个函数。其实这个定义的基本意思就是说,根据策略选择要执行的函数,而每一个策略都会有一个标识,可以称为key。而当前策略要执行的函数,可以称为value,其实就是使用key寻找value,然后执行vlaue的过程。也就是说,一个key对应一个value,从这层意思上理解,就是if-else要干的事。

小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了

小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了

那么策略模式到底优化了什么呢?

其实策略模式的核心思想与 if else如出一辙,根据不同的key动态的找到不同的业务逻辑(要执行的函数)。那它就只是如此吗?

实际上,我们口中的策略模式其实就是在代码结构上调整,用接口+实现类+分派逻辑来使代码结构可维护性更好。

小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了

小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了

一般教科书上讲到接口与实现类就结束了,其他博客上会带上提及分派逻辑。这里就不啰嗦了。现在总结一下:即使用了策略模式,所有的业务逻辑一样都少不了,改写的仍然需要写。到逻辑分派的时候,还是变相的if-else。而策略模式的优化点是抽象了出了接口,将业务逻辑封装成一个一个的实现类,任意地替换。在复杂场景(业务逻辑较多)时比直接 使用if-else 更好维护。

2. 使用策略模式优化if-else,会不会带来什么副作用呢?

我估计肯定会有很多同学这么想:我的业务逻辑就几行,你给我整一大堆类定义?有必要这么麻烦吗?我看具体的业务逻辑还需要去不同的类中,简单点不香吗!

其实这里的不满也正是策略模式的缺点:

(1) 策略类会增多

(2) 业务逻辑分散到各个实现类中,而且没有一个地方可以俯视整个业务逻辑

针对传统策略模式的缺点,在这分享一个实现思路,这个思路已经帮我们团队解决了多个复杂if else的业务场景,理解上比较容易,在技术上要使用到 Java 8的特性:Map与函数式接口。

废话少说,直接看代码:

先看两个方法:

1. processResult() :使用if-else的方法

2. processPolicyResult():使用策略模式的方法。在该方法中事先在Map中定义好了“判断条件”与“业务逻辑”的映射关系,具体看代码吧!

/**
 * 策略模式演示类
 */
public class MyService {

    /**
     * 使用if-else的解决方案
     */
    public String processResult(String key) {
        if ("checkvalue1".equals(key)) {
            return "business logic1";   
        } else if ("checkvalue2".equals(key)) {
            return "business logic2";
        }else if ("checkvalue3".equals(key)) {
            return "business logic3";
        }else if ("checkvalue4".equals(key)) {
            return "business logic4";
        }else if ("checkvalue5".equals(key)) {
            return "business logic5";
        }else if ("checkvalue6".equals(key)) {
            return "business logic6";
        }else if ("checkvalue7".equals(key)) {
            return "business logic7";
        }else if ("checkvalue8".equals(key)) {
            return "business logic8";
        }else if ("checkvalue9".equals(key)) {
            return "business logic9";
        }
        return "error;
    }

    /**
     * 用于业务逻辑分派Map
     * Function为函数式接口,下面代码中 Function<String, String> 的含义是接收一个String类型的变量,返回一个String类型的结果
     */
    private Map<String, Function<String, String>> myDispatcher = new HashMap<>();

    /**
     * 使用策略模式的方法
     */
  
    public void  policyInit() {
        myDispatcher.put("checkvalue1", key -> String.format("business logic1 for %s1", key));
        myDispatcher.put("checkvalue2", key -> String.format("business logic2 for %s2", key));
        myDispatcher.put("checkvalue3", key -> String.format("business logic3 for %s3", key));
        myDispatcher.put("checkvalue4", key -> String.format("business logic4 for %s4", key));
        myDispatcher.put("checkvalue5", key -> String.format("business logic5 for %s5", key));
        myDispatcher.put("checkvalue6", key -> String.format("business logic6 for %s6", key));
        myDispatcher.put("checkvalue7", key -> String.format("business logic7 for %s7", key));
        myDispatcher.put("checkvalue8", key -> String.format("business logic8 for %s8", key));
        myDispatcher.put("checkvalue9", key -> String.format("business logic9 for %s9", key));
    }

    public String processPolicyResult(String key) {
        //从逻辑分派Dispatcher中获得业务逻辑代码,result变量是一个lambda表达式
        Function<String, String> result = myDispatcher.get(key);
        if (result != null) {
            //执行这段表达式获得String类型的结果
            return result.apply(key);
        }
        return "error";
    }
}

下面是调用代码:

public class RunPolicy {
    private MyService myService;

    public String test(String key) {
        return myService.processPolicyResult(order);
    }
}

从这段代码中可以看到很多好处,例如:

(1)在policyInit()方法中直观地看到“判断条件”与“业务逻辑”的映射关系;

(2)不需要单独定义接口与实现类,直接使用现有的函数式接口即可;

3. 策略模式在真实场景中的应用

可能有的同学会说,我的条件判断可能非常复杂,而前面的案例只有一个条件判断(key),其实这就和数据库中通过单个字段作为索引,还是使用复合索引(多个字段共同组成索引)的问题。我们也可以用复合条件来实现策略模式,上代码:

/**
 * 策略模式类
 */
public class PolicyService {

    private Map<String, Function<String, String>> myDispatcherMulti = new HashMap<>();

    /**
     * 初始化 业务逻辑分派Map 其中value 存放的是 lambda表达式
     */
    @PostConstruct
    public void dispatcherMuitInit() {
        myDispatcherMulti.put("key_order1", key -> String.format("business logic1 for %s", key));
        myDispatcherMulti.put("key_order2_order3", key -> String.format("business logic2 for %s", key));
        myDispatcherMulti.put("key_order1_order2_order3", key -> String.format("business logic3 for %s", key));
    }

    public String processMuti(String key, int level) {
        //根据level获取不同的key
        String dKey = getDispatcherKey(key, level);

        Function<String, String> result = myDispatcherMuti.get(dKey);
        if (result != null) {
            //执行这段表达式获得String类型的结果
            return result.apply(key);
        }
        return "error";
    }

    /**
     * 根据level生成不同层次的key
     */
    private String getDispatcherKey(String key, int level) {
        StringBuilder k = new StringBuilder("key");
        for (int i = 1; i <= level; i++) {
            k.append("_" + order + i);
        }
        return k.toString();
    }
}

/**
 * 测试代码
 */
public class  TestPolicyMulti {


    private PolicyService policyService;

    public String test(String key, int level) {
        return policyService.processMuti(key, level);
    }
}

在这段代码中,key是满足一定规则的复合条件,只要设计好key的生成规则就一切ok!

可能还会有很多同学问,我的业务逻辑有很多行,在dispatcherMuitInit()方法的Map中直接写不会很长吗?直接写当然长了,我们可以抽象出一个服务类专门放业务逻辑,然后在定义中调用它就可以了,代码如下:

/**
 * 专门放业务逻辑的服务类
 */
public class ServiceUnit {

    public String task1(String key) {
        return "业务逻辑1";
    }
    public String task2(String key) {
        return "业务逻辑2";
    }
     public String task3(String key) {
        return "业务逻辑3";
    }
     public String task4(String key) {
        return "业务逻辑4";
    }
}
/**
 * 使用策略模式的类
 */
public class PolicyService {
    private ServiceUnit serviceUnit;

    private Map<String, Function<String, String>> myDispatcher = new HashMap<>();

    /**
     * 初始化规则映射
     */
    public void dispatcherInit() {
        myDispatcher.put("key_order1", key -> serviceUnit.task1(key));
        myDispatcher.put("key_order1_order2", key -> serviceUnit.task2(key)));
        myDispatcher.put("key_order1_order2_order3", key -> serviceUnit.task3(key));
        myDispatcher.put("key_order1_order2_order3_order4", key -> serviceUnit.task4(key));
    }

    public String process(String key, int level) {
        // 根据level生成对应的key
        String dKey = getDispatcherKey(key, level);

        Function<String, String> result = myDispatcher.get(dKey);
        if (result != null) {
            //执行这段表达式获得String类型的结果
            return result.apply(order);
        }
        return "error";
    }

    /**
     * 根据level生成对应的key
     */
    private String getDispatcherKey(String key, int level) {
        StringBuilder k = new StringBuilder("key");
        for (int i = 1; i <= level; i++) {
            k.append("_" + order + i);
        }
        return k.toString();
    }
}

总结:

1. 如何通过策略模式优化业务逻辑代码(可以根据自己从事的工作思考)

抽象了出了接口,将业务逻辑封装成的实现类,任意地替换。在复杂场景(业务逻辑较多)时比直接 使用if-else 更好维护。

2. 使用策略模式优化if-else,会不会带来什么副作用呢?

其实使用策略模式大多数时候会带来很多好处,不过也会有一些不足的:

(1)策略类比较多;

(2)业务逻辑分散到各个实现类中,而且没有一个地方可以俯览整个业务逻辑;

3. 实现策略模式是否有更好的方式呢?

可以用函数函数式接口实现业务逻辑,这样可以更直观观察策略和执行逻辑的关系。

喜欢我的文章,请扫描下面二维码关注 『极客起源』 公众号

小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了

也可以扫描下面二维码加李宁老师的微信:unitymarvel

小白写了一堆if-else,大神实在看不下去了,竟然用策略模式直接摆平了


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

Probability and Computing

Probability and Computing

Michael Mitzenmacher、Eli Upfal / Cambridge University Press / 2005-01-31 / USD 66.00

Assuming only an elementary background in discrete mathematics, this textbook is an excellent introduction to the probabilistic techniques and paradigms used in the development of probabilistic algori......一起来看看 《Probability and Computing》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

SHA 加密
SHA 加密

SHA 加密工具

html转js在线工具
html转js在线工具

html转js在线工具