策略模式
整理时间:2022.06.30,看了好久的代码才看懂。。。
业务简介:
希望同一个接口,当请求不同时,调用不同的业务代码。
自然而然想到了直接对请求进行判断,然后ifelse的业务逻辑判断,但由于整个通用接口所负载的业务及其复杂,所以会产生很多的ifelse屎山。
所以对通用接口进行“策略模式”设计。
为什么要使用一个接口,承载不同的业务逻辑呢?
因为如果对所有业务都分别设计不同的接口,会产生非常多的接口,而前端也无法判断究竟调用哪个接口。比如下单流程,因为车型不同,就需要对具体车型做具体逻辑,而这些不同车型的下单流程都应该聚合到通用下单流程中。
策略模式基本概念:
抽象一个策略接口和方法,然后不同的具体的类重写这个通用接口的方法。
小demo(虚假的策略模式,仅帮助前期理解,真正的实现参考后面):
通过传入不同的策略对象,执行不同的策略方法。接口抽象成通用,后续新增业务,只需新增策略对象即可。
1.抽象一个策略方法接口
public interface Strategy {
void strategyInterface();
}
2.定义一个环境角色,提供一个策略接口对外使用
public class Context {
private Strategy strategy;//策略对象(具体)
//构造器,需要传入具体的策略对象
public Context(Strategy strategy){
this.strategy = strategy;
}
//对外暴露策略方法
public void contextInterface(){
strategy.strategyInterface();//最终会调用到具体策略类重写的方法
}
}
3.具体的策略对象 里面重写的是具体的业务,后续可以一直增加
ConcreteStrategyA.java
public class ConcreteStrategyA implements Strategy {
@Override
public void strategyInterface() {
System.out.println("A的业务");
}
}
ConcreteStrategyB.java
public class ConcreteStrategyB implements Strategy{
@Override
public void strategyInterface() {
System.out.println("B的业务");
}
}
避免业务代码中大量使用ifelse判断业务类型,通过传入对象执行不同业务逻辑
/**
* @Author: liuxuewei
* @Date: 2022/6/27 15:43
* @Description:
*/
public class Client {
public static void main(String[] args) {
//选择并创建需要使用的策略对象
Strategy strategyA = new ConcreteStrategyA();
Strategy strategyB = new ConcreteStrategyB();
//创建环境
Context contextA = new Context(strategyA);
contextA.contextInterface();//A的业务
Context contextB = new Context(strategyB);
contextB.contextInterface();//B的业务
}
}
策略模式具体实现:
上面简单讲解了策略模式,现在具体实现下。
没有策略模式之前的接口,现在需要改造成策略模式:
@RestController
@RequiredArgsConstructor(onConstructor_={@Autowired})
public class CommonController {
private final StrategyHelper strategyHelper;
@RequestMapping("test/{request}")
public String common(@PathVariable("request") String request){
String result = "";
if ("A".equals(request)){//一堆ifelse业务逻辑
result = "A的业务";
}else if ("B".equals(request)){
result = "B的业务";
}else if ("C".equals(request)){
result = "C的业务";
}
return result;
}
}
1、首先,还是抽象一个策略接口和方法
/**
* @Author: liuxuewei
* @Date: 2022/6/30 14:17
* @Description:
*/
public interface Strategy {
default boolean needHandle(String request){//判断策略对象是否需要执行策略方法
return true;
}
String handle();//具体策略接口,策略对象会重写此方法来实现具体业务
}
2、实现三个策略具体的策略对象,基本是一样的
StrategyImplA
/**
* @Author: liuxuewei
* @Date: 2022/6/30 14:17
* @Description:
*/
@Component
public class StrategyImplA implements Strategy {
private final StrategyHelper strategyHelper;
@Autowired
public StrategyImplA(StrategyHelper strategyHelper){//构造器注入
this.strategyHelper = strategyHelper;
this.strategyHelper.addStrategy(this);//把自己添加到strategyHelper
}
@Override
public boolean needHandle(String request) {
if ("A".equals(request)) {//通过request给定执行策略的执行前提判断
return true;
}
return false;
}
@Override
public String handle() {//重写业务A的具体代码
return "业务A";
}
}
StrategyImplB
/**
* @Author: liuxuewei
* @Date: 2022/6/30 14:17
* @Description:
*/
@Component
public class StrategyImplB implements Strategy {
private final StrategyHelper strategyHelper;
@Autowired
public StrategyImplB(StrategyHelper strategyHelper){
this.strategyHelper = strategyHelper;
this.strategyHelper.addStrategy(this);
}
@Override
public boolean needHandle(String request) {
if ("B".equals(request)) {
return true;
}
return false;
}
@Override
public String handle() {//重写业务B的具体代码
return "业务B";
}
}
StrategyImplC
/**
* @Author: liuxuewei
* @Date: 2022/6/30 14:17
* @Description:
*/
@Component
public class StrategyImplC implements Strategy {
private final StrategyHelper strategyHelper;
@Autowired
public StrategyImplC(StrategyHelper strategyHelper){
this.strategyHelper = strategyHelper;
this.strategyHelper.addStrategy(this);
}
@Override
public boolean needHandle(String request) {
if ("C".equals(request)) {
return true;
}
return false;
}
@Override
public String handle() {//重写业务C的具体代码
return "业务C";
}
}
3、然后创建一个管理对象StrategyHelper,用来获取所有具体的策略对象
/**
* @Author: liuxuewei
* @Date: 2022/6/30 14:18
* @Description:
*/
@Component
public class StrategyHelper {
private List<Strategy> list = new ArrayList<>();//存储所有的具体策略类
public void addStrategy(Strategy strategy){//提供方法,让具体的策略类自己注入进来
list.add(strategy);
}
public List<Strategy> getList(){//返回所有的策略类对象
return this.list;
}
}
创建通用接口CommonController,承载通用请求
/**
* @Author: liuxuewei
* @Date: 2022/6/30 14:33
* @Description:
*/
@RestController
@RequiredArgsConstructor(onConstructor_={@Autowired})//替代@Autowired注解(lombok)
public class CommonController {
private final StrategyHelper strategyHelper;
@RequestMapping("test/{request}")
public String common(@PathVariable("request") String request){
StringBuilder result = new StringBuilder();
for (Strategy strategy : strategyHelper.getList()) {//遍历所有的策略类
if (strategy.needHandle(request)) {//判断哪个策略需要执行
String s = strategy.handle();//执行具体的策略
result.append(s);
}
}
return new String(result);
}
}
实现了通过入参执行不同的业务代码,而且低耦合,新增逻辑只需新增策略对象。
ps:真正的request是非常复杂的,需要通过request的来源(比如是安卓还是ios还是微信小程序等来源进行不同的逻辑,比如只有微信小程序有优惠等(虚假的假设))
ending:通用接口实现不同业务逻辑,砍掉恶心的ifelse屎山,通过策略模式进行处理。
评论区