• 设计模式胡咧咧之策略工厂实现导入导出


    策略模式(Strategy Pattern)

    定义:

    定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。

    本质:

    分离算法,选择实现

    应用场景

    何时使用

    一个系统有许多类,而区分他们的只是他们直接的行为时

    优点

    开闭原则
    避免使用多重条件判断
    扩展性良好,增加一个策略只需要实现接口即可

    缺点

    策略类数量会增多,复用可能性很小
    所有策略类都需要对外暴露

    场景

    多个类,只有算法或行为上稍有不同的场景
    算法需要自由切换的场景
    需要屏蔽算法规则

    实例举例

    导入导出
    出行方式:自行车、汽车等,每一种出行方式都是一个策略
    商场促销方式,打折、满减等
    Java LayoutManager 布局管理器

    策略模式实现导入/导出

    背景:最近在做excle的导入导出,大概10个导出,3个导入。共用的同一个记录表。思来想去用策略+简单工厂模式去除if else if …,以便更好的拓展和维护。
    1.定义一个导入接口:
    在这里插入图片描述2.创建一个策略工厂:

    	@Resource
        private Map<String, TaskExportHandleService> taskHandleServiceMap;
    
    • 1
    • 2

    3.策略枚举:

    @Getter
    public enum TaskTypeEnum {
        /**
         * 任务类型枚举
         */
        DAILY(1, "日常检查"),
        SPECIAL(2, "专项检查"),
        ENTERPRISE(3, "企业自查"),
        ;
    
        private final Integer code;
        private final String desc;
    
        TaskTypeEnum(int code, String desc) {
            this.code = code;
            this.desc = desc;
        }
    
        public static TaskTypeEnum toEnum(int id) {
            return Arrays.stream(values())
                    .filter(area -> area.getCode().equals(id))
                    .findFirst()
                    .orElse(null);
        }
    }
    
    • 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

    4.实现接口:

    @Service("ENTERPRISE")
    @Slf4j
    public class EnterpriseTaskExportHandleServiceImpl implements TaskExportHandleService {
        @Override
        public Long saveRecord(Map<String, Object> paramMap, String operator) {
            log.info("------------------------");
            log.info("执行任务:{}", TaskTypeEnum.ENTERPRISE.getDesc());
            log.info("保存记录文件,状态置为处理中");
            return 0L;
        }
    
        @Async("TaskExport")
        @Override
        public void exportFile(Map<String, Object> paramMap, Long recordId, EpUser currentUser) {
            log.info("异步处理导出文件ing");
            log.info("更新到文件记录ing");
            log.info("------------------------");
        }
    }
    
    @Service("DAILY")
    @Slf4j
    public class DailyTaskExportHandleServiceImpl implements TaskExportHandleService {
        @Override
        public Long saveRecord(Map<String, Object> paramMap, String operator) {
            log.info("------------------------");
            log.info("执行任务:{}", TaskTypeEnum.DAILY.getDesc());
            log.info("保存记录文件,状态置为处理中");
            return 0L;
        }
    
        @Async("TaskExport")
        @Override
        public void exportFile(Map<String, Object> paramMap, Long recordId, EpUser currentUser) {
            log.info("异步处理导出文件ing");
            log.info("更新到文件记录ing");
            log.info("------------------------");
        }
    }
    
    @Service("SPECIAL")
    @Slf4j
    public class SpecialTaskExportHandleServiceImpl implements TaskExportHandleService {
        @Override
        public Long saveRecord(Map<String, Object> paramMap, String operator) {
            log.info("------------------------");
            log.info("执行任务:{}", TaskTypeEnum.SPECIAL.getDesc());
            log.info("保存记录文件,状态置为处理中");
            return 0L;
        }
    
        @Async("TaskExport")
        @Override
        public void exportFile(Map<String, Object> paramMap, Long recordId, EpUser currentUser) {
            log.info("异步处理导出文件ing");
            log.info("更新到文件记录ing");
            log.info("------------------------");
        }
    }
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    5.1controller 实现:

    @RestController
    @RequestMapping("/demo")
    //@RequiredArgsConstructor 需要final
    @AllArgsConstructor
    @Anonymous
    @Slf4j
    public class TaskController {
    
        private final List<TaskExportHandler> exportHandlers;
        private final DefaultExportHandler defaultExportHandler;
    
        @PostMapping("/export")
        public Result<String> list(@RequestBody TaskExportReq req) {
            exportHandlers.stream()
                    .filter(fileHandler ->
                            fileHandler.support(req.getBusinessType()))
                    .findFirst()
                    .orElse(defaultExportHandler)
                    .exportFile(
                            req.getBusinessType(),
                            new EpUser(), req.getParamMap()
                    );
            return Result.success(null);
        }
    }
    
    • 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

    5.2导出文件req

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @ApiModel("导出文件req")
    public class TaskExportReq {
    
        @ApiModelProperty(value = "操作类型枚举 TaskTypeEnum")
        private Integer businessType;
    
        @ApiModelProperty(value = "查询参数")
        private Map<String, Object> paramMap;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    6.1方便维护,编写任务导出Handler

    @Component
    public abstract class TaskExportHandler {
        @Resource
        private Map<String, TaskExportHandleService> taskHandleServiceMap;
    
        public void exportFile(Integer businessType, EpUser currentUser, Map<String, Object> paramMap) {
            // 匹配处理器
            TaskExportHandleService taskExportHandleService = matchExportService(businessType);
    
            // 保存记录-调用保存文件
             Long recordId = taskExportHandleService.saveRecord(paramMap, currentUser.getName());
    
            // 异步执行导出
            taskExportHandleService.exportFile(paramMap, recordId, currentUser);
        }
    
        /**
         * 匹配业务类型对应的导出处理器
         */
        private TaskExportHandleService matchExportService(Integer businessType) {
            TaskTypeEnum businessTypeEnum = TaskTypeEnum.toEnum(businessType);
            if (Objects.isNull(businessTypeEnum) || Objects.isNull(taskHandleServiceMap.get(businessTypeEnum.name()))) {
                throw new ServiceException("不支持的文件操作类型");
            }
            return taskHandleServiceMap.get(businessTypeEnum.name());
        }
    
        public Boolean support(Integer businessType) {
            return Boolean.FALSE;
        }
    }
    
    • 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

    6.2默认任务Handler

    @Component
    public class DefaultExportHandler extends TaskExportHandler {
    
    }
    
    • 1
    • 2
    • 3
    • 4

    7运行效果:
    在这里插入图片描述

  • 相关阅读:
    Flink SQL你用了吗?
    Python爬虫实战:淘宝商品爬取与数据分析
    【LeetCode第362场周赛】8020.字符串转换 | 推导+矩阵快速幂+KMP | 困难
    step num 问题
    D2-读论文D2&算法题D2(复习:单链表、双链表、模拟栈)
    【C++·峰顶计划】缺省参数操作与函数重载细则
    Django的可重用HTML模板示例
    第一场面试
    Git的安装以及基础使用方法
    瑞格尔侯爵酒庄连续两年蝉联2022世界最佳葡萄园第二
  • 原文地址:https://blog.csdn.net/ss977/article/details/137876995