还在一言不合就if else或是switch?试试策略模式吧


前言

在业务开发过程中,免不了使用if、else、switch来处理不同的业务逻辑。而一但业务比较复杂,代码里面就充斥了大量的逻辑分支判断,导致代码臃肿不堪,及不好维护。所以,今天这篇文章我们就来聊一聊,如何使用策略模式,让你的代码变得更加的优雅。


一、策略模式的定义?

定义一系列算法,封装每个算法,并使他们可以互换,不同的策略可以让算法独立于使用它们的客户而变化

简单来说,策略模式就是把ifelse的行为抽象出来一个策略接口,每一种行为对应一个策略。在具体业务环境中仅持有该策略接口,根据不同的场景使用不同的实现类即可。结构图如下:
在这里插入图片描述

二、使用案例

1.业务背景

项目里有个发送微信模版消息的需求,有直播消息推送、学情消息推送、提交提醒消息推送等不同的业务类型,不同的类型需要发送不同的模版消息。

2.使用策略模式

2.1 定义一个策略接口

定义一个策略接口,定义好业务消息类型都需要用到的公用方法

public interface WxTemplateMsgStrategyService {

    /**
     * 获取消息类型
     * @return void
     **/
    String getMsgType();

    /**
     * 保存待发送的微信消息
     * @param vo
     * @return void
     **/
    void saveWxMsgWait(WxMsgDataVO vo);

    /**
     * 组装发送微信消息
     * @param waitPush
     * @return void
     **/
    WxMpTemplateMessage convertWxMsgData(WxTemplateMsgWaitPush waitPush);
}

2.2 定义各种策略

定义消息类型策略,直播消息通知、学情推送、提交提醒等实现类都实现这个接口,实现类里面就可以实现具体的业务了。由于是真实项目,这里就不贴出具体实现业务的代码,用伪代码代替了。

直播通知实现

@Slf4j
@Service
public class WxLiveMsgStrategyServiceImpl implements WxTemplateMsgStrategyService{

    @Override
    public String getMsgType() {
        return BelongTypeEnum.ZB.getName();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveWxMsgWait(WxMsgDataVO vo) {
        //执行保存直播通知的相关方法
    }

    @Override
    public WxMpTemplateMessage convertWxMsgData(WxTemplateMsgWaitPush waitPush) {
        //执行组装发送直播通知消息的相关方法
    } 
}

学情通知实现

@Slf4j
@Service
public class WxStudyMsgStrategyServiceImpl implements WxTemplateMsgStrategyService {

    @Override
    public String getMsgType() {
        return BelongTypeEnum.XQ.getName();
    }
     
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveWxMsgWait(WxMsgDataVO vo) {
        //执行保存学情通知的相关方法
    }

    @Override
    public WxMpTemplateMessage convertWxMsgData(WxTemplateMsgWaitPush waitPush) {
        //执行组装发送学情通知的相关方法
    } 
}

提醒通知实现

@Service
public class WxGraduationMsgStrategyServiceImpl implements WxTemplateMsgStrategyService {

    @Override
    public String getMsgType() {
        return BelongTypeEnum.LW.getName();
    }
     
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveWxMsgWait(WxMsgDataVO vo) {
        //执行保存提醒通知的相关方法
    }

    @Override
    public WxMpTemplateMessage convertWxMsgData(WxTemplateMsgWaitPush waitPush) {
        //执行组装发送提醒通知消息的相关方法
    } 
}

2.3 使用策略

有的文章使用了枚举、HashMap 的方式来根据策略名称映射策略实现类 ,这样是没有问题。我并没有像策略模式结构图中那样新建一个 Context 类持有策略接口,那是标准的策略模式,其实道理是一样的,关键是怎么调用策略。我这里是直接使用 Bean来调用,这样更贴近业务。

 @Override
    public String initWxMsgWait(WxMsgDataVO vo) {
        WxTemplateMsgStrategyService businessBean = getBusinessBean(vo.getBelongType().getName());
        log.info("=========获取到的bean是:========="+ businessBean);
        if (businessBean == null) {
            return "业务对象不存在";
        }
        businessBean.saveWxMsgWait(vo);
        return null;
    }

    @Override
    public WxMpTemplateMessage convertWxMsgData(WxMsgDataVO vo) {
        WxTemplateMsgStrategyService businessBean = getBusinessBean(vo.getBelongType().getName());
        log.info("=========获取到的bean是:========="+ businessBean);
        if (businessBean != null) {
            return businessBean.convertWxMsgData(vo.getWaitPush());
        }
        return null;
    }

private WxTemplateMsgStrategyService getBusinessBean(String msgType) {
        if (StringUtils.isNotBlank(msgType)) {
            //获取所有实现该策略接口的bean
            List<WxTemplateMsgStrategyService> maintenanceBeans = SpringContextKit.getBeans(WxTemplateMsgStrategyService.class);
            if (CollUtil.isNotEmpty(maintenanceBeans)) {
                for (WxTemplateMsgStrategyService bean : maintenanceBeans) {
                    if (msgType.equals(bean.getMsgType())) {
                        return bean;
                    }
                }
            }
        }
        return null;
    }

3.使用对比

未使用策略模式的时候,所有的通知类型实现都在一个类里面,导致代码又长又不好阅读,若再新加一个通知类型的需求,则需在该类里面在添加一个判断类型的分支,实现相关业务,不易扩展;

使用策略模式后,代码变得更简洁,若有新的通知类型也更加容易扩展;

三、策略模式的优缺点

优点:

  • 1、可以避免多重条件选择语句,减少繁琐的 if、switch 判断逻辑。
  • 2、符合开闭原则,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  • 3、代码优雅、可复用、可读性好。

缺点:

  • 1、策略如果很多的话,会产生很多策略类,造成策略类膨胀。
  • 2、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

总结

好了,以上就是今天要讲的内容。本文通过一个实例介绍了策略模式的使用,具体应用到项目中还需要视情况而定,不能一味的追求设计,过度设计,否则适得其反。

感谢大家的阅读,若觉得对你有帮助的话,动动小手,还不忘点赞评论支持一波哟,你的支持是我最大的动力~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java升级之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值