博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【设计模式】优雅的策略模式
阅读量:6412 次
发布时间:2019-06-23

本文共 4922 字,大约阅读时间需要 16 分钟。

借助强大的Spring,优雅地使用策略模式


啥是佩奇 策略模式

定义:指对象有某个行为,但是在不同的 场景 中,该行为有不同的 实现算法

主要解决:在有多种算法相似的情况下,使用if...else...所带来的复杂和难以维护。
关键代码:实现同一个接口。


应用场景

public Integer getResult(Integer num1, Integer num2, OperationTypeEnum typeEnum) {	// 判断操作类型	if (OperationTypeEnum.ADD == typeEnum) {		// 相加		return num1 + num2;	} else if (OperationTypeEnum.SUBTRACT == typeEnum) {		// 相减		return num1 - num2;	} else if (OperationTypeEnum.MULTIPLY == typeEnum) {		// 相乘		return num1 * num2;	}	throw new RuntimeException("没有对应的操作类型");}复制代码

场景:有两个Integer类型的数num1和num2,根据入参的操作类型不同(场景不同),执行相应的相加、减、乘处理逻辑(实现算法)。这样我们的应用场景就跟上面说的策略模式定义就对应上了。

缺点:随着实现逻辑的 复杂 化,以及操作类型的 扩展if...else...逻辑块会越来越臃肿,也越来越 不易维护


优雅的策略模式

中针对上述场景实现了一套经典的策略模式解决方式。

不过本文意在借助 Spring的@Autowired注解可以直接注入类的集合类型 这一特点,优雅地实现策略模式。

  1. 相加、相减、相乘三种操作方式实现同一个接口OperationService的同一方法doOperation()
public interface OperationService {    /**     * 执行操作     *     * @param num1     * @param num2     * @return     */    Integer doOperation(Integer num1, Integer num2);}复制代码
@Service("addOperationServiceImpl")public class AddOperationServiceImpl implements OperationService {    /**     * 执行相加操作     *     * @param num1     * @param num2     * @return     */    @Override    public Integer doOperation(Integer num1, Integer num2) {        return num1 + num2;    }}复制代码
@Service("subtractOperationServiceImpl")public class SubtractOperationServiceImpl implements OperationService {    /**     * 执行相减操作     *     * @param num1     * @param num2     * @return     */    @Override    public Integer doOperation(Integer num1, Integer num2) {        return num1 - num2;    }}复制代码
@Service("multiplyOperationServiceImpl")public class MultiplyOperationServiceImpl implements OperationService {    /**     * 执行相乘操作     *     * @param num1     * @param num2     * @return     */    @Override    public Integer doOperation(Integer num1, Integer num2) {        return num1 * num2;    }}复制代码
  1. 三种操作的 类型 和操作 实现类Bean的name,维护到枚举OperationTypeEnum中作为字典使用。
public enum OperationTypeEnum {    /**     * 相加     */    ADD(1, "相加", "addOperationServiceImpl"),    /**     * 相减     */    SUBTRACT(2, "相减", "subtractOperationServiceImpl"),    /**     * 相乘     */    MULTIPLY(3, "相乘", "multiplyOperationServiceImpl");    /**     * 唯一编码     */    private Integer code;    /**     * 描述     */    private String desc;    /**     * 对应策略模式实现类Bean的name     */    private String strategyBeanName;    /* 构造方法 */    /* getter & setter */}复制代码

如上述代码,各操作实现类Bean的名字,即各实现类上方@Service注解括号中的标识,与操作类型通过枚举OperationTypeEnum实现了映射。

  1. 计算操作策略接口CalculateOperationStrategy只有一个方法calculate()。 接口不再赘述,直接看实现类。
@Service("calculateOperationStrategy")public class CalculateOperationStrategyImpl implements CalculateOperationStrategy {    /**     * '将所有类型为OperationService的Bean注入为一个Map     * key为Bean的name     */    @Autowired    private Map
operationServiceMap; /** * 计算 * * @param num1 * @param num2 * @param type * @return */ @Override public Integer calculate(Integer num1, Integer num2, OperationTypeEnum type) { // 该操作类型对应的策略模式实现类Bean的name String strategyBeanName = type.getStrategyBeanName(); if (operationServiceMap.get(strategyBeanName) != null) { // 执行对应策略模式实现类的doOperation方法 return operationServiceMap.get(strategyBeanName).doOperation(num1, num2); } else { throw new RuntimeException("没有对应的操作类型"); } }复制代码
  • 我们通过@Autowired接口直接将所有类型为OperationService的Bean注入为一个Map,Map的 keyBean的name。该步骤的具体实现原理请看我的上一篇文章:。
  • 刚已知传入的操作类型枚举OperationTypeEnum中包含对应实现类Bean的name,所以我们可以这个name作为key,从刚才的Map中get到对应操作类型的实现类,最后直接调用该实现类的doOperation()方法。

  1. 最后看测试类
@RunWith(SpringRunner.class)@SpringBootTest(classes = PpValidatorApplication.class)public class CalculateOperationStrategyTest {    @Autowired    private CalculateOperationStrategy calculateOperationStrategy;    @Test    public void testCalculate() {        Integer num1 = 66;        Integer num2 = 6;        System.out.println("计算方式:"                 + OperationTypeEnum.ADD.getDesc()                + " ---> 计算结果:"                 + calculateOperationStrategy.calculate(num1, num2, OperationTypeEnum.ADD));        System.out.println("计算方式:"                 + OperationTypeEnum.SUBTRACT.getDesc()                + " ---> 计算结果:"                 + calculateOperationStrategy.calculate(num1, num2, OperationTypeEnum.SUBTRACT));        System.out.println("计算方式:"                 + OperationTypeEnum.MULTIPLY.getDesc()                + " ---> 计算结果:"                 + calculateOperationStrategy.calculate(num1, num2, OperationTypeEnum.MULTIPLY));    }}复制代码

执行结果如下

计算方式:相加 ---> 计算结果:72计算方式:相减 ---> 计算结果:60计算方式:相乘 ---> 计算结果:396复制代码

!!!完美!!!


总结

  • 策略模式可以根据程序上下文中类型不同,执行类型对应的实现逻辑。后续修改、替换都很方便。
  • 借助 Spring的@Autowired注解可以直接注入类的集合类型 这一特点,可以优雅地实现策略模式。具体实现原理请戳:。
  • 各实现类只需要维护各自类中的doOperation()方法即可。
  • 如需扩展类型,只需要新增一个实现类,实现OperationService接口,并将实现类Bean的名字和类型维护到字典枚举OperationTypeEnum中。

分享自我的简书

转载于:https://juejin.im/post/5c4920fbf265da61163a1b08

你可能感兴趣的文章
HAProxy+Hive构建高可用数据挖掘集群
查看>>
网站相关技术探究keepalive_timeout:
查看>>
思科路由器PPOE client+NAT解决地址回流问题测试
查看>>
Windows Server 2012新特性:证书申请加密
查看>>
zabbix监控之Centos基于LNMP环境安装
查看>>
Linux文本比较命令:diff
查看>>
使用nginx+Apache负载均衡及动静分离
查看>>
C#基础知识整理:基础知识(10) 静态
查看>>
MongoDB实战(1)MongoDB安装与存储结构
查看>>
sccm 2007 r2 step by step 之十八 报表-报表点
查看>>
FreeMarker中调用Java方法的实现
查看>>
Kubernetes & Docker 容器网络终极之战
查看>>
DVWA系列之15 文件包含漏洞利用
查看>>
puppet on windows
查看>>
10个最酷的linux单行命令
查看>>
Windows 10 技术预览版
查看>>
Linux还是亲生的好,实战自制Linux操作系统
查看>>
Using Half-NAT Mode Load Balancer In Solaris 11
查看>>
分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(2月27日-3月4日)
查看>>
【基础】华为设备链路捆绑大全实战精简版
查看>>