可以制作什么网站,建筑行业人才网,湘潭网站建设方案咨询,flash网站报价策略模式
策略模式#xff1a;百度百科中引述为#xff1a;指对象有某个行为#xff0c;但是在不同的场景中#xff0c;该行为有不同的实现算法。
策略模式是对算法的包装#xff0c;是把使用算法的责任和算法本身分割开来#xff0c;委派给不同的对象管理。策略模式通…策略模式
策略模式百度百科中引述为指对象有某个行为但是在不同的场景中该行为有不同的实现算法。
策略模式是对算法的包装是把使用算法的责任和算法本身分割开来委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面作为一个抽象策略类的子类。用一句话来说就是“准备一组算法并将每一个算法封装起来使得它们可以互换”。【此处的算法可以理解为解决业务需求的方法。】 换一种说法就是一个类的行为或其算法可以在运行时更改。我们把它降维到代码层面 用人话翻译一下就是 运行时我给你这个类的方法传不同的“key”你这个方法会执行不同的业务逻辑。细品一下这不就是 if else 干的事吗 举个实际的例子审核流程请假和调休都是提交审核审批这个审批的时候要干的事就不同了。如果你传的Type是请假诶那就要扣你工资了起码全勤是没了。如果type是调休的话那就没事了工资照常发。那正常的代码结构一般就是下面这样了
if(请假){//todo 扣你工资xxx
} else if(调休){//todo 工资照发
}其实策略模式的核心思想和 if else如出一辙根据不同的key动态的找到不同的业务逻辑那它就只是如此吗
实际上我们口中的策略模式其实就是在代码结构上调整用接口实现类分派逻辑来使代码结构可维护性好点。 一般教科书上讲解到接口与实现类就结束了其他博客上会带上提及分派逻辑。这里就不啰嗦了。
小结一下即使用了策略模式你该写的业务逻辑照常写到逻辑分派的时候还是变相的if else。而它的优化点是抽象了出了接口将业务逻辑封装成一个一个的实现类任意地替换。在复杂场景业务逻辑较多时比直接 if else 来的好维护些。
就是几个if else场景我需要用到策略模式 我想小伙伴们经常有这样的不满我的业务逻辑就3 4 行你给我整一大堆类定义有必要这么麻烦吗我看具体的业务逻辑还需要去不同的类中简单点行不行。
其实我们所不满的就是策略模式带来的缺点
1、策略类会增多 2、业务逻辑分散到各个实现类中而且没有一个地方可以俯视整个业务逻辑 针对传统策略模式的缺点在这分享一个实现思路这个思路已经帮我们团队解决了多个复杂if else的业务场景理解上比较容易代码上需要用到Java8的特性——利用Map与函数式接口来实现。
直接show代码结构为了简单演示一个思路代码用String 类型来模拟一个业务BO
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;Service
public class TestService {/*** 业务逻辑分派Map* Function为函数式接口下面代码中 FunctionString, String 的含义是接收一个Stirng类型的变量返回一个String类型的结果*/private MapString, FunctionString, String checkResultDispatcher new HashMap();/*** 初始化 业务逻辑分派Map 其中value 存放的是 lambda表达式*/PostConstructpublic void checkResultDispatcherInit() {checkResultDispatcher.put(请假, type - String.format(%s扣你工资, type));checkResultDispatcher.put(调休, type - String.format(%s不扣你工资, type));}public String getCheckResultSuper(String type) {//从逻辑分派Dispatcher中获得业务逻辑代码result变量是一段lambda表达式FunctionString, String result checkResultDispatcher.get(type);if (result ! null) {//执行这段表达式获得String类型的结果return result.apply(type);}return 不正确的业务类型;}}测试:
RestController
public class TestCtrl {AutowiredTestService testService;PostMapping(/v1/demo/test)public String test2(String type) {return testService.getCheckResultSuper(type);}
}使用接口测试工具得到如下结果 鲁迅曾说过“每解决一个问题就会引出更多的问题”。我们一起来看看这样的实现有什么好处会带来什么问题。 好处很直观
在一段代码里直观的看到判断条件与业务逻辑的映射关系不需要单独定义接口与实现类直接使用现有的函数式接口什么不知道函数式接口快去了解而实现类直接就是业务代码本身。
不好的点
需要团队成员对lambda表达式有所了解(什么Java17都出来了还有没用上Java8新特性的小伙伴)
接下来我举几个在业务中经常遇到的if else场景并用Map函数式接口的方式来解决它 有的小伙伴会说我的判断条件有多个啊而且很复杂你之前举个例子只有单个判断逻辑而我有多个判断逻辑该怎么办呢 很好解决写一个判断逻辑的方法Map的key由方法计算出
Service
public class TestService {/*** 业务逻辑分派Map* Function为函数式接口下面代码中 FunctionString, String 的含义是接收一个Stirng类型的变量返回一个String类型的结果*/private MapString, FunctionString, String checkResultDispatcher new HashMap();private static String QJ_PASS 请假_通过;private static String QJ_REJECT 请假_驳回;private static String TX_PASS 调休_通过;private static String TX_REJECT 调休_驳回;/*** 初始化 业务逻辑分派Map 其中value 存放的是 lambda表达式*/PostConstructpublic void checkResultDispatcherInit() {checkResultDispatcher.put(QJ_PASS, type - String.format(%s成功,扣你工资, type));checkResultDispatcher.put(QJ_REJECT, type - String.format(%s失败老实上班, type));checkResultDispatcher.put(TX_PASS, type - String.format(%s成功不扣你工资放心去浪, type));checkResultDispatcher.put(TX_REJECT, type - String.format(%s失败老实上班, type));}public String getCheckResultSuper(String type, String state) {//从逻辑分派Dispatcher中获得业务逻辑代码result变量是一段lambda表达式String key getDispatcherKey(type,state);FunctionString, String result checkResultDispatcher.get(key);if (result ! null) {//执行这段表达式获得String类型的结果return result.apply(type);}return 不正确的业务类型;}/*** 判断条件方法*/private String getDispatcherKey(String type, String state) {return type _ state;}}测试 controller修改如下:
PostMapping(/v1/demo/test)
public String test2(String type, String state) {return testService.getCheckResultSuper(type,state);
}测试结果如下所示: 可以看出只要设计好key的生成规则多判断逻辑的需求是完全可以满足的。 既然鲁迅说过“每解决一个问题就会引出更多的问题”。那么我们接下来看看还有什么问题
如果我的业务逻辑有很多很多行在checkResultDispatcherMuitInit()方法的Map中直接写不会很长吗 直接写当然长了我们可以抽象出一个service服务专门放业务逻辑然后在定义中调用它就好了
Service
public class BizUnitService {public String qjPass(String type) {return type 通过各种花式操作;}public String qjReject(String type) {return type 失败各种花式操作;}public String txPass(String type) {return type 成功各种花式操作;}public String txReject(String type) {return type 失败各种花式操作;}}Service
public class TestService {AutowiredBizUnitService bizUnitService;/*** 业务逻辑分派Map* Function为函数式接口下面代码中 FunctionString, String 的含义是接收一个Stirng类型的变量返回一个String类型的结果*/private MapString, FunctionString, String checkResultDispatcher new HashMap();private static String QJ_PASS 请假_通过;private static String QJ_REJECT 请假_驳回;private static String TX_PASS 调休_通过;private static String TX_REJECT 调休_驳回;/*** 初始化 业务逻辑分派Map 其中value 存放的是 lambda表达式*/PostConstructpublic void checkResultDispatcherInit() {checkResultDispatcher.put(QJ_PASS, type - bizUnitService.qjPass(type));checkResultDispatcher.put(QJ_REJECT, type - bizUnitService.qjReject(type));checkResultDispatcher.put(TX_PASS, type - bizUnitService.txPass(type));checkResultDispatcher.put(TX_REJECT, type - bizUnitService.txReject(type));}public String getCheckResultSuper(String type, String state) {//从逻辑分派Dispatcher中获得业务逻辑代码result变量是一段lambda表达式String key getDispatcherKey(type,state);FunctionString, String result checkResultDispatcher.get(key);if (result ! null) {//执行这段表达式获得String类型的结果return result.apply(type);}return 不正确的业务类型;}/*** 判断条件方法*/private String getDispatcherKey(String type, String state) {return type _ state;}}测试结果如下所示: 道不行乘桴浮于海. --《论语·公冶长》