这里涉及到一个关键词:策略模式,那么到底什么是策略模式呢?本文就来好好给你们讲讲策略模式,你们能够带着以下几个问题来阅读本文:算法
要会带这个问题,须要先弄清楚策略模式的定义,首先来看策略模式的教科书定义:数据库
策略模式(Strategy Pattern):定义一系列算法,将每个算法封装起来,并让它们能够相互替换。 策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。 策略模式是一种对象行为型模式。app
这里的算法其实就是业务逻辑,为了更形象,干脆将其理解为一个函数。其实这个定义的基本意思就是说,根据策略选择要执行的函数,而每个策略都会有一个标识,能够称为key。而当前策略要执行的函数,能够称为value,其实就是使用key寻找value,而后执行vlaue的过程。也就是说,一个key对应一个value,从这层意思上理解,就是if-else要干的事。ide
那么策略模式到底优化了什么呢?函数
其实策略模式的核心思想与 if else一模一样,根据不一样的key动态的找到不一样的业务逻辑(要执行的函数)。那它就只是如此吗?测试
实际上,咱们口中的策略模式其实就是在代码结构上调整,用接口+实现类+分派逻辑来使代码结构可维护性更好。优化
通常教科书上讲到接口与实现类就结束了,其余博客上会带上说起分派逻辑。这里就不啰嗦了。如今总结一下:即便用了策略模式,全部的业务逻辑同样都少不了,改写的仍然须要写。到逻辑分派的时候,仍是变相的if-else。而策略模式的优化点是抽象了出了接口,将业务逻辑封装成一个一个的实现类,任意地替换。在复杂场景(业务逻辑较多)时比直接 使用if-else 更好维护。ui
我估计确定会有不少同窗这么想:个人业务逻辑就几行,你给我整一大堆类定义?有必要这么麻烦吗?我看具体的业务逻辑还须要去不一样的类中,简单点不香吗!spa
其实这里的不满也正是策略模式的缺点:设计
(1) 策略类会增多 (2) 业务逻辑分散到各个实现类中,并且没有一个地方能够俯视整个业务逻辑
针对传统策略模式的缺点,在这分享一个实现思路,这个思路已经帮咱们团队解决了多个复杂if else的业务场景,理解上比较容易,在技术上要使用到Java8的特性:Map与函数式接口。
废话少说,直接看代码:
先看两个方法:
/** * 策略模式演示类 */ public class MyService { /** * 使用if-else的解决方案 */ public String proce***esult(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)不须要单独定义接口与实现类,直接使用现有的函数式接口便可;
可能有的同窗会说,个人条件判断可能很是复杂,而前面的案例只有一个条件判断(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(); } }
总结:
如何经过策略模式优化业务逻辑代码(能够根据本身从事的工做思考)
抽象了出了接口,将业务逻辑封装成的实现类,任意地替换。在复杂场景(业务逻辑较多)时比直接 使用if-else 更好维护。
其实使用策略模式大多数时候会带来不少好处,不过也会有一些不足的:
(1)策略类比较多;
(2)业务逻辑分散到各个实现类中,并且没有一个地方能够俯览整个业务逻辑;
能够用函数函数式接口实现业务逻辑,这样能够更直观观察策略和执行逻辑的关系。