在策略模式中一个类的行为或者其算法在运行是可以进行改变,这种的类型也可以叫做行为型模式。
基本结构
今天和朋友要去公园玩儿,那么就要选择出行方式,那么创建一个出行的接口,创建自行车、公交、步行等行为类,并且都继承出行的接口,再创建我的选择类(Context)来选择出行方式。至此大体完成。
/**
* @author Surpass
* @Package com.hkrt.demo
* @Description: 出行方式(工具)
* @date 2021/1/15 16:16
*/
public interface Strategy {
void goOutTool();
}
/**
* @author Surpass
* @Package com.hkrt.demo.strategy
* @Description: 公交车
* @date 2021/1/15 16:20
*/
public class BusWayStrategy implements Strategy{
@Override
public void goOutTool() {
System.out.println("今天坐公交车出去玩儿");
}
}
/**
* @author Surpass
* @Package com.hkrt.demo.strategy
* @Description: 步行方式
* @date 2021/1/15 16:19
*/
public class WalkWayStrategy implements Strategy {
@Override
public void goOutTool() {
System.out.println("今天要步行出去玩儿");
}
}
/**
* @author Surpass
* @Package com.hkrt.demo.strategy
* @Description: 开车
* @date 2021/1/15 16:21
*/
public class CarWayStrategy implements Strategy {
@Override
public void goOutTool() {
System.out.println("今天自己开车出去玩儿");
}
}
/**
* @author Surpass
* @Package com.hkrt.demo.strategy
* @Description: 选择行为(上下文)
* @date 2021/1/15 16:22
*/
public class StrategyContext {
private Strategy strategy;
public StrategyContext(Strategy strategy) {
this.strategy = strategy;
}
public void goOut(){
strategy.goOutTool();
}
}
/**
* @author Surpass
* @Package com.hkrt.demo.strategy
* @Description: 我和朋友准备出去玩儿
* @date 2021/1/15 16:24
*/
public class PlayTest {
public static void main(String[] args) {
/**
* 选择步行出去玩儿
*/
StrategyContext walkWayStrategy = new StrategyContext(new WalkWayStrategy());
walkWayStrategy.goOutTool();
/**
* 选择坐公交出去玩儿
*/
StrategyContext busWayStrategy = new StrategyContext(new BusWayStrategy());
busWayStrategy.goOutTool();
/**
* 选择自己开车出去玩儿
*/
StrategyContext carWayStrategy = new StrategyContext(new CarWayStrategy());
carWayStrategy.goOutTool();
}
}
Connected to the target VM, address: '127.0.0.1:11631', transport: 'socket'
今天要步行出去玩儿
今天坐公交车出去玩儿
今天自己开车出去玩儿
Disconnected from the target VM, address: '127.0.0.1:11631', transport: 'socket'
这样一个简单的策略就是出来了,如果出现新增的策略,只需要实现公共的出行方式接口,然后写自己的逻辑就OK了。
接了个需求,对接第三方接口进行数据的校验,每一个第三方都是一套规范,考虑到后续的可扩展性,和内部的统一,使用策略类进行实现。
channelCode
)。在这里我去掉了Context上下文,直接在逻辑代码中注入校验接口,根据配置中的第三方数据的 channelCode
判断走哪个第三方接口( channelCode
的值就是该第三方接口类在Spring中的beanName)。
public interface BusinessAuthChannelService {
/**
* 企业信息要素验证
* @param dto 校验数据
* @return java.util.Map<java.lang.String , java.lang.Object>
* @throws
* @author Surpass
* @date 2021/1/7 15:56
*/
Map<String, Object> auth(AuthChannelDto dto);
}
@Slf4j
@Service("qcc")
public class QccAuthChannelServiceImpl implements BusinessAuthChannelService {
private Gson gson = new Gson();
/**
* 鉴权查询
* @param dto
* @return java.util.Map<java.lang.String , java.lang.Object>
* @throws
* @author Surpass
* @date 2021/1/11 13:51
*/
@Override
public Map<String, Object> auth(AuthChannelDto dto) {
Map<String, Object> resultMap = new HashMap<>();
return resultMap;
}
}
@Slf4j
@RestController
@RequestMapping("/businessAuthChannel")
public class BusinessAuthChannelController {
@Autowired
private BusinessAuthChannelConfigService businessAuthChannelConfigService;
@Autowired
private BusinessAuthChannelOrderService businessAuthChannelOrderService;
private Gson gson = new Gson();
/**
* 企业信息要素验证
* @param dto
* @return java.util.Map<java.lang.String , java.lang.Object>
* @throws
* @author Surpass
* @date 2021/1/7 15:38
*/
@RequestMapping("/auth")
public Map<String,Object> auth(@RequestBody AuthChannelDto dto){
log.info("企业信息要素验证,要素鉴权参数:"+gson.toJson(dto));
Map<String, Object> map = new HashMap<>(2);
Map<String, Object> authResult = null;
//校验参数
boolean validateParameter = this.validateParameter(dto);
if (!validateParameter){
map.put("rspCode", "99");
map.put("rspMsg", "参数校验失败");
log.info("企业信息要素验证,返回数据:"+map);
return map;
}
//查询鉴权通道
BusinessAuthChannelConfig config = this.getAuthChannelConfig(dto);
//判断能够鉴权的标识
boolean flag = false;
if (config != null){
//是否存在该通道编码的调用service实现类(spring bean中存在通道编码的bean)
boolean existBean = SpringUtil.getApplicationContext().containsBean(config.getChannelCode());
if (existBean){
flag = true;
}
}
if (!flag){
map.put("rspCode", "99");
map.put("rspMsg", "找不到可用通道");
log.info("企业信息要素验证,返回数据:"+map);
this.saveBusinessAuthChannelOrder(dto, authResult, config);
return map;
}
//调用鉴权通道
BusinessAuthChannelService authChannelService =
(BusinessAuthChannelService)SpringUtil.getBean(config.getChannelCode());
authResult = authChannelService.auth(dto);
//保存信息记录
this.saveBusinessAuthChannelOrder(dto, authResult, config);
Map<String, Object> resultMap = (Map<String, Object>)authResult.get("resultMap");
log.info("企业信息要素验证,返回数据:"+resultMap);
return resultMap;
}
/**
* 鉴权要素参数校验
* @param dto
* @return boolean
* @throws
* @author Surpass
* @date 2021/1/12 15:32
*/
private boolean validateParameter(AuthChannelDto dto){
}
/**
* 根据参数条件查询可用的鉴权通道
* @param dto
* @return com.p4.risk.entity.BusinessAuthChannelConfig
* @throws
* @author Surpass
* @date 2021/1/12 15:32
*/
private BusinessAuthChannelConfig getAuthChannelConfig(AuthChannelDto dto){
//根据参数在配置表中查询第三方接口配置信息
}
/**
* 保存操作记录
* @param dto 企业信息鉴权信息
* @param authResult 鉴权结果
* @param config 企业鉴权通道配置
* @return void
* @throws
* @author Surpass
* @date 2021/1/12 15:33
*/
private void saveBusinessAuthChannelOrder(AuthChannelDto dto, Map<String, Object> authResult,
BusinessAuthChannelConfig config){
}
}
解释一下:主要是 auth
这个方法时主要流程,根据参数查询出来的第三方接口配置字段的 channelCode
,使用SpringUtil在Spring中查找是否存在有该值的beanName,如果不存在,则直接保存操作记录后返回。如果存在则使用 SpringUtil.getBean(channelCode)
获得该编码的bean,然后调用 authResult = authChannelService.auth(dto)
就进入到第三方校验实现类中进行校验,校验完毕后保存操作记录,流程结束。
代码不全,但注释应该足够了,如果对上述代码有疑问的烦请留言,如果各位喜欢这篇文章,劳烦各位伸出小手点个赞,收个藏,关个注。