Java中实用的策略模式【Strategy】

一、简介

我们知道Java中有许多的设计模式,总共32个左右。常见的比如简单工厂、建造者、原型、代理、桥接等,这些设计模式相当于是一个规范,主要是总结出来便于大家理解开发的一种算法思路。

今天主要是给大家介绍一下我们常见的策略模式,这个模式主要是一种行为设计模式,它能让你在运行时动态地改变对象的行为。在Java中,我们可以通过接口和实现类来实现动态替换策略的行为。

二、基础架构

策略模式有三个重要的部分:环境类、策略接口和具体策略。环境类接收一个策略对象,并将执行流程委托给这个策略对象。策略接口定义了一个公共操作,具体策略是对策略接口的实现。

策略模式的主要优点在于它可以让你在运行时改变对象的行为。而且你可以独立于其他代码定义新的策略。

java 复制代码
public interface Strategy {
    void strategyMethod(); 
}

public class ConcreteStrategyA implements Strategy {
    public void strategyMethod() {
        System.out.println("执行策略A");
    }
}

public class ConcreteStrategyB implements Strategy {
    public void strategyMethod() {
        System.out.println("执行策略B");
    }
}

public class Context {
    private Strategy strategy;
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    public void contextMethod() {
        strategy.strategyMethod();
    }
}   

三、策略模式的应用实例

现在我有一个简单的需求demo,主要是通过同学的code,计算出对应code同学的得分。

代码如下所示:

1、接口(包含了对用的code,和得分的计算逻辑,其他实现接口的可以直接使用调用加分、减分)

java 复制代码
public interface StudentScoreHandler {

    /**
     * 获取学生分数
     */
    BigDecimal score();

    /**
     * 学生code
     */
    String code();

    /**
     * 加分 通用处理
     */
    default BigDecimal extraPoints(BigDecimal original, BigDecimal addend) {
        return original.add(addend);
    }

    /**
     * 减分 通用处理
     */
    default BigDecimal minusPoints(BigDecimal original, BigDecimal subtrahend) {
        return original.subtract(subtrahend);
    }
}

2、具体策略(001编号的学生得分+10,002的学生得分-10)

001学生实现:

java 复制代码
@Component
public class KkStudentHandler implements StudentScoreHandler {

    @Override
    public BigDecimal score() {
        return minusPoints(new BigDecimal(String.valueOf(90.00)), BigDecimal.valueOf(10.00));
    }

    @Override
    public String code() {
        return "001";
    }
}

002学生实现:

java 复制代码
@Component
public class XmStudentHandler implements StudentScoreHandler {

    @Override
    public BigDecimal score() {
        return extraPoints(new BigDecimal(String.valueOf(90.00)), BigDecimal.valueOf(10.00));
    }

    @Override
    public String code() {
        return "002";
    }
}

3、Service类

这里有多钟做法,我这里采用的是将所有的策略实现在初始化的时候就放入map里面,后续来了直接可以取。

java 复制代码
@Service
public class StudentScoreService {

    @Resource
    private List<StudentScoreHandler> studentScoreHandlerList;

    private Map<String, StudentScoreHandler> stringStudentScoreHandlerMap;

    @PostConstruct
    private void init() {
        stringStudentScoreHandlerMap = studentScoreHandlerList.stream()
                .collect(Collectors.toMap(StudentScoreHandler::code, it -> it));
    }

    public BigDecimal score(String code) {
        StudentScoreHandler studentScoreHandler = stringStudentScoreHandlerMap.get(code);
        if (ObjectUtil.isEmpty(studentScoreHandler)) {
            return null;
        }
        return studentScoreHandler.score();
    }
}

4、控制器

java 复制代码
@RequestMapping("/student")
@RestController
@Slf4j
public class StudentScoreController {
    @Resource
    private StudentScoreService studentScoreService;

    @GetMapping("/score")
    public ResultBean<BigDecimal> score(@RequestParam("code") String code) {
        return ResultBean.create(studentScoreService.score(code));
    }
}

5、Postman测试

只需要将对应的学生code传入即可 获取对应的学生分数

001

002

相关推荐
何似在人间57515 分钟前
多级缓存模型设计
java·jvm·redis·缓存
多云的夏天17 分钟前
ubuntu24.04-MyEclipse的项目导入到 IDEA中
java·intellij-idea·myeclipse
Fanxt_Ja29 分钟前
【数据结构】红黑树超详解 ---一篇通关红黑树原理(含源码解析+动态构建红黑树)
java·数据结构·算法·红黑树
Aphelios38034 分钟前
TaskFlow开发日记 #1 - 原生JS实现智能Todo组件
java·开发语言·前端·javascript·ecmascript·todo
weixin_448771721 小时前
使用xml模板导出excel
xml·java·excel
烁3472 小时前
每日一题(小白)模拟娱乐篇27
java·数据结构·算法·娱乐
魔道不误砍柴功2 小时前
2025年Java无服务器架构实战:AWS Lambda与Spring Cloud Function深度整合
java·架构·serverless
smileNicky2 小时前
SpringBoot系列之集成Redisson实现布隆过滤器
java·spring boot·redis·布隆过滤器
隔壁小查2 小时前
【后端开发】初识Spring IoC与SpringDI、图书管理系统
java·spring·okhttp
程序员沉梦听雨3 小时前
外观模式详解
java·设计模式·外观模式