1、使用场景
关键业务中使用大量的if else 判断,此时可以使用策略模式进行优化
2、应用
场景1:当入参为1时,执行计费的逻辑,入参为2时执行退费的逻辑,需要入参和出参的
java
// 计费
if (chargeOrReturnReq.getCalcMode() == 1) {
String useCode = doLowCharge(detailsList);
....
}
// 退费
if (chargeOrReturnReq.getCalcMode() == 2) {
String refundCode = doLowRefund(detailsList);
....
}
使用策略模式优化
优化后此处代码为
java
// Map.get方法根据key获取对应的策略,key = 1计费 key=2 退费,返回的是对应计费或者退费的方法
Function<List<HisLowChargeDetails>, List<HisLowChargeOrReturnRes>> listStringFunction = DO_LOW_CHARGE_OR_REFUND_STRATEGY.get(chargeOrReturnReq.getCalcMode());
// 方法.apply 调用具体的计费/退费方法并获取返回值
List<HisLowChargeOrReturnRes> resOneList = listStringFunction.apply(detailsList);
策略类
java
package com.miyite.consumables.modules.external.strategy;
import cn.hutool.extra.spring.SpringUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class HisChargeOrRefundStrategy {
// 业务中需要的依赖注入
private static HisChargeItemDao hisChargeItemDao;
private static HisLowChargeDetailsDao hisLowChargeDetailsDao;
private static HwfRefundService hwfRefundService;
private static HwfUseDetailsDao hwfUseDetailsDao;
private static HwfWarehouseInDetailsDao hwfWarehouseInDetailsDao;
private static HwfUseService hwfUseService;
private static void setContext() {
// 使用hutool类获取Bean对象
hisChargeItemDao = SpringUtil.getBean(HisChargeItemDao.class);
hisLowChargeDetailsDao = SpringUtil.getBean(HisLowChargeDetailsDao.class);
hwfRefundService = SpringUtil.getBean(HwfRefundService.class);
hwfUseDetailsDao = SpringUtil.getBean(HwfUseDetailsDao.class);
hwfWarehouseInDetailsDao = SpringUtil.getBean(HwfWarehouseInDetailsDao.class);
// 使用hutool类获取Bean对象
hwfUseService = SpringUtil.getBean(HwfUseService.class);
}
// 策略的Map集合 value是一个方法 方法中第一个调用本策略的 是入参 第二个是出参
public static final Map<Integer, Function<List<HisLowChargeDetails>, List<HisLowChargeOrReturnRes>>> DO_LOW_CHARGE_OR_REFUND_STRATEGY = new HashMap<>();
static {
/* 计费策略 */
DO_LOW_CHARGE_OR_REFUND_STRATEGY.put(1, HisChargeOrRefundStrategy::doLowCharge);
/* 退费策略 */
DO_LOW_CHARGE_OR_REFUND_STRATEGY.put(2,HisChargeOrRefundStrategy::doLowRefund);
}
private static List<HisLowChargeOrReturnRes> doLowCharge(List<HisLowChargeDetails> detailsList) {
setContext();
..计费业务..
}
private static List<HisLowChargeOrReturnRes> doLowRefund(List<HisLowChargeDetails> detailsList) {
setContext();
..退费业务..
}
}
场景2 登录方式有PC端登录 PDA登录,有多个入参,并且不需要出参的
1、调用本策略的代码
java
// 执行终端身份认证
TerminalAuthentication terminalAuthentication = TERMINAL_STRATEGY.get(loginInfo.getSource());
terminalAuthentication.executeAuthentication(loginInfo, request, response, chain);
2、策略模式接口
java
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 终端认证
*/
@FunctionalInterface
public interface TerminalAuthentication {
/**
* 执行认证
*
* @param loginInfo 登录信息
* @param request 请求对象
* @param response 响应对象
* @param chain 过滤器链
*/
void executeAuthentication(LoginInfo loginInfo, HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException;
}
3、策略模式类
java
import com.auth0.jwt.interfaces.Claim;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
import static com.medical.nurse.cache.keys.SecurityRedisKey.LOGINED_ITEM_PERMISSION;
import static com.medical.nurse.cache.keys.SecurityRedisKey.LOGINED_ITEM_TOKEN;
/**
* 终端认证策略
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class TerminalAuthenticationStrategy {
/**
* 定义不同终端的认证实现
*/
public static final Map<LoginSource, TerminalAuthentication> TERMINAL_STRATEGY = new HashMap<>();
/* 初始化终端认证策略 */
static {
/* PC端认证策略 */
TERMINAL_STRATEGY.put(LoginSource.PC, (loginInfo, request, response, chain) -> {
// pc端登录认证逻辑
......
});
/* PDA端认证策略 */
TERMINAL_STRATEGY.put(LoginSource.PDA, (loginInfo, request, response, chain) -> {
// pc端登录认证逻辑
......
});
}
}