设计模式之策略模式

什么是策略模式?

策略模式主要的目的是将算法的定义和调用分开,将算法定义在不同的策略类中,算法的调用根据具体的条件来动态调用策略类。

策略模式的模型图

client(算法调用者): 维护一个策略类的引用,根据不同的条线来选择调用具体的策略实现 Strategy(策略抽象类): 是所有策略类的父类,可以是抽象类亦可以是接口,抽象策略类定义的方法需要具体的策略实现类去实现。 StrategyA/StrategyA(策略具体实现类): 实现策略接口或者继承策略抽象类,实现具体的算法,可以根据具体的业务实现动态的增减策略实现类。

策略模式应用示例

需求:系统需要对接不同的银行来实现融资申请的操作,每个银行都有相应的数据加密算法对请求参数进行加密并调用相关SDK进行通信,客户端通过界面选择找哪家银行进行融资申请,根据银行的简称找到具体的银行实现类,进行融资申请的推送。

代码示例:

java 复制代码
// 定义策略父类(可以是接口也可是抽象类)
public interface FinancingHandler {
    void sendFinancingApply(FinancingRequest financingRequest);
}

// 策略实现类
@Component(value = "cmbc")
@Slf4j
public class CMBCHandler implements FinancingHandler{
    @Override
    public void sendFinancingApply(FinancingRequest financingRequest) {
        log.info("向工商银行推送融资申请信息....");
        log.info("融资请求参数:{}",financingRequest);
    }
}

// 策略实现类
@Component(value = "cbc")
@Slf4j
public class CBCHandler implements FinancingHandler{
    @Override
    public void sendFinancingApply(FinancingRequest financingRequest) {
        log.info("向建设银行推送融资申请信息....");
        log.info("融资请求参数:{}",financingRequest);
    }
}
// 枚举常量
public enum BankEnum {
    CMBC("cmbc", "中国工商银行"),
    CBC("cbc", "中国建设银行");

    private String simpleName;
    private String bankName;

    BankEnum(String simpleName, String bankName) {
        this.simpleName = simpleName;
        this.bankName = bankName;
    }
    public String getSimpleName() {
        return simpleName;
    }
}
// 融资请求实体
@Data
@ToString
public class FinancingRequest {
    private String contractNo;
    private BigDecimal amount;
    private String applyName;
    private String applyAccount;
}
// 定义策略实现类的获取方法
@Component
public class SpringApplicationContextUtil implements ApplicationContextAware {

    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }


    public  FinancingHandler getFinancingHandler(String beanName) {
        return (FinancingHandler) context.getBean(beanName);
    }
}
// 业务调用入口
@Component
public class FinancingBusService {

    @Autowired
    private SpringApplicationContextUtil springApplicationContextUtil;

    public void sendFinancingApply(FinancingRequest financingRequest, BankEnum bankEnum){
        FinancingHandler financingHandler = springApplicationContextUtil.getFinancingHandler(bankEnum.getSimpleName());
        financingHandler.sendFinancingApply(financingRequest);
    }

}

// 单元测试
@SpringBootTest
public class FinancingTest {

    @Autowired
    private FinancingBusService financingBusService;

    @Test
    public void test1(){
        FinancingRequest request = new FinancingRequest();
        request.setApplyName("tony");
        request.setApplyAccount("111111");
        request.setAmount(new BigDecimal(10000));
        financingBusService.sendFinancingApply(request, BankEnum.CMBC);
    }

}

预期展示

适用场景以及优缺点

适用场景

一种需求或者一种场景,需要动态的选择多种算法中的某一种算法,这些算法都是抽象父类的一种实现。

优缺点

优点

  1. 策略模式符合开闭原则,可通过实现父类的方法来动态的增减新的子类。
  2. 策略模式可以将重复的公共代码统一移动到父类中,子类只负责实现差异的算法,能更好的实现代码的复用。

缺点

  1. 调用者必须清楚的知道不同算法之间的差异,并自行选择调用那种策略。
  2. 不支持同时使用多个策略类。
相关推荐
编程洪同学41 分钟前
Spring Boot 中实现自定义注解记录接口日志功能
android·java·spring boot·后端
-$_$-1 小时前
【LeetCode 面试经典150题】详细题解之滑动窗口篇
算法·leetcode·面试
GraduationDesign1 小时前
基于SpringBoot的蜗牛兼职网的设计与实现
java·spring boot·后端
颜淡慕潇2 小时前
【K8S问题系列 | 20 】K8S如何删除异常对象(Pod、Namespace、PV、PVC)
后端·云原生·容器·kubernetes
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS安康旅游网站(JAVA毕业设计)
java·vue.js·spring boot·后端·kafka·开源·旅游
DogDaoDao3 小时前
leetcode 面试经典 150 题:矩阵置零
数据结构·c++·leetcode·面试·矩阵·二维数组·矩阵置零
搬码后生仔3 小时前
将 ASP.NET Core 应用程序的日志保存到 D 盘的文件中 (如 Serilog)
后端·asp.net
Suwg2093 小时前
《手写Mybatis渐进式源码实践》实践笔记(第七章 SQL执行器的创建和使用)
java·数据库·笔记·后端·sql·mybatis·模板方法模式
凡人的AI工具箱4 小时前
每天40分玩转Django:Django文件上传
开发语言·数据库·后端·python·django
spcodhu4 小时前
在 Ubuntu 上搭建 MinIO 服务器
linux·后端·minio