首页 > 其他分享 >使用策略模式优化你的代码

使用策略模式优化你的代码

时间:2023-09-19 22:36:07浏览次数:35  
标签:积分 代码 模式 PointTypeEnum points 接口 sendPoint 优化 public

策略模式简介

策略模式(Strategy Pattern:Define a family of algorithms,encapsulate each one,and make them interchangeable.)中文解释为:定义一组算法,然后将这些算法封装起来,以便它们之间可以互换,属于一种对象行为型模式。总的来说策略模式是一种比较简单的模式,听起来可能有点费劲,其实就是定义一组通用算法的上层接口,各个算法实现类实现该算法接口,封装模块使用类似于 Context 的概念,Context 暴漏一组接口,Context 内部接口委托到抽象算法层。

策略模式的通用类图如下:

包含的角色如下:

  • 上下文角色(Context):该角色一般是一个实现类或者封装类,起到一定的封装及隔离作用,实际接受请求并将请求委托给实际的算法实现类处理,避免外界对底层策略的直接访问;
  • 抽象策略角色(Strategy):该角色一般是一个抽象角色,为接口或者抽象类扮演,定义具体策略角色的公共接口;
  • 具体策略角色(ConcreteStrategy):实现抽象策略角色的接口,为策略的具体实现类。

使用策略模式优化代码逻辑判断

假设我们有个积分发放功能,需要根据不同的积分类型来发分,我们的积分类型假设如下:

/**
 * 积分类型枚举
 */
public enum PointTypeEnum {
    COURSE_LEARN,
    COURSE_COMMENT,
    EBOOK_READ,
    LIVE_WATCH,
}

然后我们实现一个发放积分的方法:

/**
 * 指定积分类型,发分
 * @param pointTypeEnum 积分类型
 * @param points 要发的积分
 */
private static void sendPoint(PointTypeEnum pointTypeEnum, Integer points) {
    switch (pointTypeEnum) {
        case COURSE_COMMENT:
            log.info("评论课程,获得 {} 积分", points);
            break;
        case COURSE_LEARN:
            log.info("学习课程,获得 {} 积分", points);
            break;
        case EBOOK_READ:
            log.info("阅读电子书,获得 {} 积分", points);
            break;
        case LIVE_WATCH:
            log.info("观看直播,获得 {} 积分", points);
            break;
        default:
            break;
    }
}

这里只举例了 4 种积分类型,实际情况可能并不止这么多,而且每种积分发放逻辑都不相同,如果一味的在 switch case 中堆代码是肯定不行,根据我们的设计原则,尽量保证高内聚、低耦合,很显然这种方式是不可取的。

使用策略模式优化下上面的代码,首先我们需要一个策略接口,即积分发放接口:

/**
 * 积分发放接口,各个积分类型需要实现该接口,自定义发放逻辑
 */
public interface PointSendInterface {
    /**
     * 发放积分
     * @param points 要发放的积分
     */
    void sendPoint(Integer points);

    /**
     * 积分类型
     * @return
     */
    PointTypeEnum sendType();
}

然后不同的积分类型需要实现该接口,以便自定义其积分发放规则:

@Slf4j
@Service
public class CourseCommentPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("评论课程,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.COURSE_COMMENT;
    }
}

@Slf4j
@Service
public class CourseLearnPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("学习课程,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.COURSE_LEARN;
    }
}

@Slf4j
@Service
public class EbookReadPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("阅读电子书,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.EBOOK_READ;
    }
}

@Slf4j
@Service
public class LiveWatchPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("观看直播,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.LIVE_WATCH;
    }
}

最后我们要实现一个积分发放的 Context 给业务方使用,大致如下:

/**
 * 积分发放类
 */
@Component
public class PointSendContext {
    @Autowired
    private List<PointSendInterface> sendStrategyList;

    private final Map<PointTypeEnum, PointSendInterface> SEND_STRATEGY_MAP = new HashMap<>();

    @PostConstruct
    public void init() {
        sendStrategyList.forEach(strategy -> {
            SEND_STRATEGY_MAP.put(strategy.sendType(), strategy);
        });
    }

    /**
     * 发放积分
     * @param pointTypeEnum 积分类型
     * @param points 要发的分
     */
    public void sendPoint(PointTypeEnum pointTypeEnum, Integer points) {
        PointSendInterface sendStrategy = SEND_STRATEGY_MAP.get(pointTypeEnum);
        // 调用具体实现类发放积分
        sendStrategy.sendPoint(points);
    }
}

这里我们通过 @Autowired 自动注入 PointSendInterface 接口的所有实现类 sendStrategyList,然后通过 @PostConstruct 的初始化方法将每一个实现类组装成 SEND_STRATEGY_MAP 对象以便后续直接通过 pointType 可以映射出来该 pointType 对应的发分方法。调用的话就比较简单了,没有了 switch case 的冗长:

@SpringBootTest
class PointSendContextTest {
    @Autowired
    private PointSendContext pointSendContext;

    @Test
    void sendPoint() {
        pointSendContext.sendPoint(PointTypeEnum.COURSE_LEARN, 20);
    }
}

标签:积分,代码,模式,PointTypeEnum,points,接口,sendPoint,优化,public
From: https://www.cnblogs.com/vipzhou/p/17716017.html

相关文章

  • 个人项目互评代码分析
    个人项目互评代码分析软件2105-刘一凡在看完金颖希同学的代码后,我有了一些看法与建议,在这篇博客中将对她的代码进行分析,并提出一些建议性的优化方案。个人拙见,希望能为项目的进一步改进提供一些思路。整体结构:代码结构相对清晰,分为数学题生成器和用户两部分,其中每个数学题生成......
  • 3种 Springboot 全局时间格式化方式,别再写重复代码了
    From: https://developer.aliyun.com/article/771395简介: 别再写重复代码了本文收录在个人博客:www.chengxy-nds.top,技术资料共享,同进步时间格式化在项目中使用频率是非常高的,当我们的 API 接口返回结果,需要对其中某一个 date 字段属性进行特殊的格式化处理,通常会用到......
  • 希尔排序:优化的插入排序
    希尔排序(ShellSort)是一种插入排序的改进算法,它通过比较相距一定间隔的元素进行排序,逐步减小间隔,最终实现整体有序。本文将详细介绍希尔排序的工作原理,提供示例和Python、Go、Java以及C语言的实现代码。希尔排序的基本思想希尔排序的核心思想是将整个待排序序列分割成若干个子序列,......
  • Jest 匹配器:简化测试代码,提高测试效率
    Jest匹配器在软件开发中,测试是一个非常重要的环节。而在JavaScript开发中,Jest是一个非常流行的测试框架。Jest提供了丰富的功能和工具,其中的匹配器(Matchers)是其中之一。匹配器可以帮助我们编写更简洁、更高效的测试代码。本文将介绍Jest匹配器的使用方法和一些常用的匹配器......
  • K8s部署Nacos 2.0.3集群模式(外置mysql数据库)
    来源:https://www.woniusnail.com/?p=1691Nacos 具体介绍就不介绍了,详细的官方都有。本次主要介绍在k8s集群中部署Nacos集群(3节点),数据库使用外置的mysql,相比使用官方的在k8s内创建数据库的方案维护更方便,所有nacos配置全部保存在数据库中,不用担心重启掉线等异常导致配置文......
  • 为什么 Python 代码在函数中运行得更快?
    哈喽大家好,我是咸鱼当谈到编程效率和性能优化时,Python常常被调侃为“慢如蜗牛”有趣的是,Python代码在函数中运行往往比在全局范围内运行要快得多小伙伴们可能会有这个疑问:为什么在函数中运行的Python代码速度更快?今天这篇文章将会解答大家心中的疑惑原文链接:https://stac......
  • Xor-Subsequence (字典树优化DP)
     思路;明显的是,后一个i要从前面一个进行更新, 利用dpeasy版本ai<=200,发现当n>=300时,对他是没有影响的,这样比较好记录ans进行更新,利用数据结构处理hard版本拆位,利用字典树dp,把参数变成相同的参数,a[i]和i,(比大小:前K位一样第K+1位不一样......
  • 8-更大并、可混合接口模式压测的FastHttpUser
    FastHttpUser和HttpUser相比,这个类的运行占用更少压测机的CPU并且可以支撑更大的并发数,并且可以配合gevent类来实现接口混合模式压测(一个user在几乎同一时间并发多个api请求),直接上例子importtimefromgevent.poolimportPoolfromlocustimportFastHttpUser,taskdefa......
  • 11-NO-GUI模式运行测试以及输出测试结果
    CommandLine运行Locust性能测试一、使用headless参数,直接运行测试实际压测场景,使用linux服务器作为压测机一般是没有可视化桌面的,因此需要用到--headless参数来来运行locust测试,如下locust-fyourlocustfile.py--headless在命令行中输入后回车,locust就会自动开始执行yourl......
  • 详解RAID6种磁盘阵列模式
    所谓RAID就是RedundantArrayofIndependentDisk的缩写,中文意思是“独立冗余磁盘阵列”,简单来说就是一种利用多个硬盘来提高系统对磁盘的读写速度及其数据安全系数的一种技术。RAID技术开始一般用于服务器或大型工作站上面,但随着RAID技术的不断成熟,现在不少的家用PC的主板都内置......