一、前言

策略模式可能是在工作中使用最多的,也是在面试中最常提到的,代码重构和优化的必备!

小编之前也是一直说,其实没有真正的实战;最近有了机会实战了一下,来分享一下使用心得和在企业级的使用!

二、策略模式

1. 什么是策略模式

策略模式,英文全称是 Strategy Design Pattern。在 GoF 的《设计模式》一书中,它是这样定义的:

定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。

2. 策略模式结构组成

  • Strategy:抽象策略类,一般为接口或者策略类
  • ConcreteStrategy:具体算法实现策略类
  • Context:环境或者上下文类,用于统一执行具体策略

其实以上三部分用白话文来解释就是:

需要一个接口和策略进行规范和约束接口和方法,这时需要一些具体的实现算法类去继承或者实现刚刚的接口和策略,最后通过一个环境或者上下文,也可以叫做工厂根据类型进行调用具体的算法!

3. 使用场景

  • 避免冗长的 if-else 或 switch 分支判断
  • 需要动态地在几种算法中选择一种
  • 对客户隐藏具体策略 (算法) 的实现细节,彼此完全独立,扩展其余不受影响

具体场景一般为:

  • 支付方式选择
  • 打折、满减方式选择
  • 根据类型调用不同的系统

4. 优缺点

优点:

  • 扩展性好
  • 符合开闭原则
  • 符合单一职责原则
  • 可读性好
  • 便于维护
  • 避免多层判断

缺点:

  • 策略过多,导致策略类
  • 对新手读代码不友好

三、策略模式实战

1. 实战例子

今天小编根据春夏秋冬四季需要做不同的事情来演示一下策略模式的使用方案;

需求是:

如果是春天,就要去放风筝

如果是夏天,就要去游泳

如果是秋天,就要去看枫叶

如果是冬天,就要去打雪仗

没有使用策略模式的话,肯定就是

if-if else进行实现!

下面就带大家体会一下具体使用哈!!

2. 策略接口

/**
* 四季策略
* @author wangzhenjun
* @date 2022/12/1 9:30
*/
public interface SeasonsStrategy { /**
* 根据季节去执行不同的方案
* @param seasons
* @return
*/
String execute(String seasons);
}

3. 春季具体实现

/**
* 春季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("spring")
public class SpringStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) { return seasons + "来了!我们一起去放风筝吧!";
}
}

4. 夏季具体实现

/**
* 夏季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("summer")
public class SummerStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) { return seasons + "来了!我们一起去游泳吧!";
}
}

5. 秋季具体实现

/**
* 秋季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("autumn")
public class AutumnStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) { return seasons + "来了!我们一起去放看枫叶吧!";
}
}

6. 冬季具体实现

/**
* 冬季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("winter")
public class WinterStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) { return seasons + "来了!我们一起去打雪仗吧!";
}
}

7. 上下文工厂实现

private Map<String, SeasonsStrategy> seasonsMap;这是最重要的,很多时候我们都知道怎么进行策略和实现怎么写,不知道怎么统一去放进去,来进行调用,可以自己放在map中。当然spring已经给我们组装好了,只要按需调用即可!

核心:

Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类!

/**
* 环境或者上下文类,用于统一执行具体策略
* @author wangzhenjun
* @date 2022/12/1 9:56
*/
@Component
public class SeasonsFactory {
/**
* Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
*/
@Autowired
private Map<String, SeasonsStrategy> seasonsMap; /**
* 处理四季统一入口方法
* @param seasons
* @param beanName
* @return
*/
public String handle(String seasons,String beanName){
// 根据bean的名称获取对应的算法处理类
SeasonsStrategy seasonsStrategy = seasonsMap.get(beanName);
String execute = seasonsStrategy.execute(seasons);
return execute;
}
}

8. controller处理

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController { @Autowired
private SeasonsFactory seasonsFactory; @GetMapping("/strategyTest/{seasons}/{beanName}")
public Result strategyTest(@PathVariable("seasons") String seasons,@PathVariable("beanName") String beanName){
String handle = seasonsFactory.handle(seasons, beanName);
return Result.success(handle);
}
}

9. 测试

http://localhost:8087/test/strategyTest/春天/spring



http://localhost:8087/test/strategyTest/夏天/summer

四、总结

在策略模式中定义了一系列算法,将每一个算法封装起来,并让它们可以相互替换,互不影响。

策略模式得益于按照开闭原则进行设计,各个具体算法按照单一职责原则设计; 提高了代码的复用性,对客户隐藏具体策略 (算法) 的实现细节,彼此完全独立,扩展其余不受影响;避免if-else 或 switch 分支语句判断;其缺点在于客户端必须知道所有的策略类,增加了系统中类的个数。

在日常开发一般用于消除多重判断,有时候不要为了用设计模式而用设计模式,一定要结合业务场景,过度设计也是很致命的!!

如果对你有帮助,还请不要吝啬您的发财小手,你的一键三连是我写作的动力,谢谢大家哈!!


可以看下小编的微信公众号,文章首发看,欢迎关注,一起交流哈!!

Springboot整合策略模式概念->使用场景->优缺点->企业级实战的更多相关文章

  1. springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

  2. 功能:SpringBoot整合rabbitmq,长篇幅超详细

    SpringBoot整合rabbitMq 一.介绍 消息队列(Message Queue)简称mq,本文将介绍SpringBoot整合rabbitmq的功能使用 队列是一种数据结构,就像排队一样,遵循 ...

  3. SpringBoot整合SpringSecurity示例实现前后分离权限注解

    SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证 作者:Sans_ juejin.im/post/5da82f066fb9a04e2a73daec 一.说 ...

  4. SpringBoot整合MyBatisPlus配置动态数据源

    目录 SpringBoot整合MyBatisPlus配置动态数据源 SpringBoot整合MyBatisPlus配置动态数据源 推文:2018开源中国最受欢迎的中国软件MyBatis-Plus My ...

  5. SpringBoot整合Swagger和Actuator

    前言 本篇文章主要介绍的是SpringBoot整合Swagger(API文档生成框架)和SpringBoot整合Actuator(项目监控)使用教程. SpringBoot整合Swagger 说明:如 ...

  6. springboot整合websocket高级版

    目录 sockjs介绍 产生的原因 环境搭建 springboot整合sockjs 使用场景 聊天室开发 点对点通信 群聊 效果 总结 加入战队 微信公众号 上一章节我们说了websocket的优缺点 ...

  7. springboot整合Shiro功能案例

    Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...

  8. SpringBoot整合Swagger2(Demo示例)

    写在前面 由于公司项目采用前后端分离,维护接口文档基本上是必不可少的工作.一个理想的状态是设计好后,接口文档发给前端和后端,大伙按照既定的规则各自开发,开发好了对接上了就可以上线了.当然这是一种非常理 ...

  9. 001 SringBoot基础知识及SpringBoot整合Mybatis

    1.原有Spring优缺点分析 (1)优点 Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品.无需开发重量级的Enterprise J ...

  10. Redis-基本概念、java操作redis、springboot整合redis,分布式缓存,分布式session管理等

    NoSQL的引言 Redis数据库相关指令 Redis持久化相关机制 SpringBoot操作Redis Redis分布式缓存实现 Resis中主从复制架构和哨兵机制 Redis集群搭建 Redis实 ...

随机推荐

  1. 一篇文章带你了解网页框架——Vue简单入门

    一篇文章带你了解网页框架--Vue简单入门 这篇文章将会介绍我们前端入门级别的框架--Vue的简单使用 如果你以后想从事后端程序员,又想要稍微了解前端框架知识,那么这篇文章或许可以给你带来帮助 温馨提 ...

  2. NLP之基于Seq2Seq和注意力机制的句子翻译

    Seq2Seq(Attention) @ 目录 Seq2Seq(Attention) 1.理论 1.1 机器翻译 1.1.1 模型输出结果处理 1.1.2 BLEU得分 1.2 注意力模型 1.2.1 ...

  3. Codeforces Round #829 (Div. 2)/CodeForces1754

    CodeForces1754 注:所有代码均为场上所书 Technical Support 解析: 题目大意 给定一个只包含大写字母 \(\texttt{Q}\) 和 \(\texttt{A}\) 的 ...

  4. XPAND模板语言语法1.0

    XPAND模板语言语法1.0 Xpand模板语言一般写在以.xpt为结尾的文本文件中 ,以"« »" 作为开头和结尾  .Xpand语言主要包括以下几个标签: «IMPORT», ...

  5. 【JavaSE】JDK 环境配置

    下载 JDK 网站网址:oracle 安装 JDK 双击运行安装包 配置环境变量

  6. Java多线程(5):CAS

    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 在JDK1.5之前,Java的多线程都是靠synchronized来保证同步的,这会引起很多性能问题,例如死锁.但随着Java的不断完善,JNI ...

  7. C# String.Empty和""的区别

    个人观点 Empty其实是string类中的一个静态的只读字段,因为是静态成员变量,所以String.Empty是在设计String类的时候就已经在内存上分配好了空间,故在使用Empty这个变量的时候 ...

  8. vue 祖先组件操作后代组件方法

    前言:最近写代码遇到一问题:祖先级别的组件怎么操作孙子的儿子的组件方法(是不是已经绕晕了),在网上搜了半天都是父子传参,父子操作,晕晕乎乎的想起了bus(事件总线), 原理就是:是在vue原型上挂载( ...

  9. Abp.Zero 手机号免密登录验证与号码绑定功能的实现(一):验证码模块

    这是一篇系列博文,我将使用Abp.Zero搭建一套集成手机号免密登录验证与号码绑定功能的用户系统: Abp.Zero 手机号免密登录验证与号码绑定功能的实现(一):验证码模块 Abp.Zero 手机号 ...

  10. @RequestBody 注解问题

    /**         * 不管你是get 请求 还是 post 请求  只要你的参数名称叫做abc          * 这里的abc 必须和 postman里面的key 一样          * ...