策略模式簡單運用
背景是 根據不同的渠道,處理不同的任務,相比if else 可以不用動主邏輯程式碼,程式碼可維護性好點,每次處理不同渠道的任務只需要改對應的實現,缺點就是的增加類的數量,核心就是多型。
1. 定義介面
public interface TaskFileHandleService {
/**
* 獲取任務型別
* @return
*/
TaskTypeEnum getTaskType();
/**
* 任務檔案處理
* @param task
*/
void taskFileHandle(Task task);
}
2. 定義宏觀類
注入 所有介面實現類,迴圈匹配即可。
@Service
public class TaskFileHandleStrategy {
@Autowired
private List<TaskFileHandleService> taskFileHandleServiceList;
/**
* 處理邏輯
* @param task
*/
public void handle(Task task){
for (int i = 0; i < taskFileHandleServiceList.size(); i++) {
TaskFileHandleService taskFileHandleService = taskFileHandleServiceList.get(i);
TaskTypeEnum taskType = taskFileHandleService.getTaskType();
if(Objects.equals(TaskTypeEnum.of(task.getTaskType()),taskType)){
taskFileHandleService.taskFileHandle(task);
}
}
}
}
3.使用
注入對應的類 taskFileHandleStrategy.handle(task) 即可,主邏輯不用動,每次新加任務,加一個具體實現類即可,也就是所謂面向 介面程式設計的靈活性。
@Autowired
private TaskFileHandleStrategy taskFileHandleStrategy;
@Override
public void handleTaskJob(List<Task> taskList) {
if(CollectionUtil.isNotEmpty(taskList)){
// 根據任務型別解析檔案
taskList.stream().forEach(task -> {
// 匯出任務 執行緒池 處理
if(Objects.equals(TaskTypeEnum.DOWNLOAD_AIRCRAFT_CHEF.getValue(),task.getTaskType())){
executor.execute(() ->{
doTask(task);
});
}else {
doTask(task);
}
});
}
}
/**
* 做任務
* @param task
*/
private void doTask(Task task){
try {
handleTask(task);
}catch (Exception e){
log.error("處理任務失敗 任務id={} 任務名稱={} 任務資訊",task.getId(),task.getName(),e);
task.setFailReason(ExceptionUtil.stacktraceToOneLineString(e,Constants.EXCEPTION_MSG_SIZE));
handleFailed(task);
}
}
/**
* 處理任務
* @param task
*/
private void handleTask(Task task) {
Task newTask = new Task();
newTask.setId(task.getId());
newTask.setStatus(TaskStatusEnum.PROCESSING.getValue());
newTask.setStartTime(LocalDateTime.now());
updateById(newTask);
taskFileHandleStrategy.handle(task);
handleSuccess(task);
}