Springboot中优雅实现策略模式(一)

Springboot中优雅实现策略模式(一)

Wangjie Lv2

策略模式简述

策略模式的核心是将行为和行为的具体实现分离的模式,有以下特点:

可以避免代码中出现大量的if else判断
可以增加新的策略而不影响调用端的逻辑代码

策略模式UML类图

核心思想是在业务使用处采用接口进行关系依赖,然后根据具体的策略选择具体的实现类执行相关的计算方法

通过Springboot的功能快速实现策略模式

功能需求描述

需要通过统一的启动任务接口启动不同类型的任务,不同类型的任务启动方式不同,通过任务类型区分不同的任务进行启动

策略模式接口定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface TaskHandler {

/**
* 获取任务类型
* @return 任务类型
*/
String taskType();

/**
* 启动任务
* @param taskInfo 任务信息
* @return 是否启动成功
*/
Boolean start(TaskInfo taskInfo);

/**
* 停止任务
* @param taskInfo 任务信息
* @return 是否停止成功
*/
Boolean stop(TaskInfo taskInfo);

}

定义策略接口,包含三个方法:

taskType:获取任务类型,由具体策略实现类标记具体处理哪种类型的任务
start:启动任务
stop:终止任务

具体策略实现类

  • mysql任务策略类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @Slf4j
    @Service
    public class MysqlTaskHandler implements TaskHandler{
    @Override
    public String taskType() {
    return "mysql";
    }

    @Override
    public Boolean start(TaskInfo taskInfo) {
    log.info("mysql task start...");
    return Boolean.TRUE;
    }

    @Override
    public Boolean stop(TaskInfo taskInfo) {
    log.info("mysql task stopped...");
    return Boolean.TRUE;
    }
    }
  • sqlserver策略实现类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @Slf4j
    @Service
    public class SqlserverTaskHandler implements TaskHandler{
    @Override
    public String taskType() {
    return "sqlserver";
    }

    @Override
    public Boolean start(TaskInfo taskInfo) {
    log.info("sqlserver task start...");
    return Boolean.TRUE;
    }

    @Override
    public Boolean stop(TaskInfo taskInfo) {
    log.info("sqlserver task stopped...");
    return Boolean.TRUE;
    }
    }

策略的注册与调用

  • 策略注册

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    @Slf4j
    @Service
    public class TaskHandlerRegister implements CommandLineRunner, ApplicationContextAware {

    private ApplicationContext applicationContext;

    private final Map<String, TaskHandler> taskHandlerMap = new HashMap<>();

    @Override
    public void run(String... args) throws Exception {
    final Map<String, TaskHandler> beansOfType = applicationContext.getBeansOfType(TaskHandler.class);
    for (TaskHandler taskHandler : beansOfType.values()) {
    taskHandlerMap.put(taskHandler.taskType(), taskHandler);
    log.info("TaskHandler type:{} has been registered...", taskHandler.taskType());
    }
    }

    /**
    * 根据任务类型获取具体策略
    * @param taskType 任务类型
    * @return 具体策略实现类
    */
    public TaskHandler getTaskHandler(String taskType) {
    final TaskHandler taskHandler = taskHandlerMap.get(taskType);
    if (Objects.isNull(taskHandler)) {
    throw new RuntimeException(String.format("taskType:%s can not resolve", taskType));
    }
    return taskHandler;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
    }
    }
  • CommandLineRunner接口:在SpringBoot项目初始化完成后执行该接口的run方法,可以用于做一些初始化操作,这里利用该方法进行策略的发现和注册,将策略的具体实现类通过Map进行缓存

  • ApplicationContextAware接口:实现该接口的类可以获取到Springboot的上下文执行环境ApplicationContext,通过上下文执行环境可以获取到SpringBoot容器中的Bean对象,这里通过applicationContext.getBeansOfType(TaskHandler.class)方法获取实现TaskHandler接口的所有实例Bean,即为该策略的全部实现

  • getTaskHandler方法:通过任务类型获取具体的策略实现类,便于在业务端进行调用

具体业务端调用策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Slf4j
@Service
public class TaskService {

private final TaskHandlerRegister taskHandlerRegister;

public TaskService(TaskHandlerRegister taskHandlerRegister) {
this.taskHandlerRegister = taskHandlerRegister;
}

public Boolean startTask(TaskInfo taskInfo) {
// 通过任务类型获取到具体的任务处理类
final TaskHandler taskHandler = taskHandlerRegister.getTaskHandler(taskInfo.getTaskType());
// 调用具体任务处理类的start方法启动任务
return taskHandler.start(taskInfo);
}

public Boolean stopTask(TaskInfo taskInfo) {
final TaskHandler taskHandler = taskHandlerRegister.getTaskHandler(taskInfo.getTaskType());
return taskHandler.stop(taskInfo);
}

}

在具体的业务端注入TaskHandlerRegister服务,在启动任务时通过任务类型获取到具体的实现策略,taskHandlerRegister.getTaskHandler(taskInfo.getTaskType());然后调用具体策略的具体方法。

  • Title: Springboot中优雅实现策略模式(一)
  • Author: Wangjie
  • Created at : 2024-11-08 11:25:28
  • Updated at : 2024-11-19 19:53:58
  • Link: https://wj0410.github.io/2024/11/08/Springboot中优雅实现策略模式/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments