侧边栏壁纸
博主头像
这就是之谦博主等级

我们的征途是星辰大海

  • 累计撰写 182 篇文章
  • 累计创建 3 个标签
  • 累计收到 16 条评论
标签搜索

目 录CONTENT

文章目录

策略模式

这就是之谦
2022-06-30 / 0 评论 / 0 点赞 / 715 阅读 / 1,450 字
温馨提示:
本文最后更新于 2022-06-30,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

策略模式

整理时间: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);
    }
}

image-20220630151323619

实现了通过入参执行不同的业务代码,而且低耦合,新增逻辑只需新增策略对象。

ps:真正的request是非常复杂的,需要通过request的来源(比如是安卓还是ios还是微信小程序等来源进行不同的逻辑,比如只有微信小程序有优惠等(虚假的假设))

ending:通用接口实现不同业务逻辑,砍掉恶心的ifelse屎山,通过策略模式进行处理。

0

评论区