一、简介
我们知道Java中有许多的设计模式,总共32个左右。常见的比如简单工厂、建造者、原型、代理、桥接等,这些设计模式相当于是一个规范,主要是总结出来便于大家理解开发的一种算法思路。
今天主要是给大家介绍一下我们常见的策略模式,这个模式主要是一种行为设计模式,它能让你在运行时动态地改变对象的行为。在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,和得分的计算逻辑,其他实现接口的可以直接使用调用加分、减分)
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学生实现:
@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学生实现:
@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里面,后续来了直接可以取。
@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、控制器
@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