zoukankan      html  css  js  c++  java
  • 结合Spring实现策略模式

      最近系统需要对不同维度的数据进行差异化计算,也就会使用不同算法。为了以后更加容易扩展,结合Spring框架及策略模式对实现架构做了系统设计。

    1. 定义策略接口(Strategy):

    import com.dmall.scfc.biz.dao.model.ScfcScoreField;
    import com.dmall.scfc.biz.dao.model.ScfcScoreFieldValue;
    import com.dmall.scfc.biz.dto.ScoreModelDimensionDTO;
    
    import java.util.List;
    
    /**
     * @author wangxuexing
     * @descrption 数据抽取策略
     * @date 2019/12/4
     */
    public interface Strategy {
        /**
         * 是否匹配策略
         * @param scoreField 基础字段
         * @return
         */
        boolean isMatch(ScfcScoreField scoreField);
        /**
         * 根据具体字段抽取数据
         * @param dimensionRule
         * @return
         */
        List<ScfcScoreFieldValue> extractData(ScoreModelDimensionDTO dimensionRule) throws Exception;
    }

    2. 实现具体策略

    import java.util.List;
    
    /**
     * @author wangxuexing
     * @descrption scf-score 基础维度表按模型设置日期聚合策略
     * @date 2019/12/4
     */
    @Service
    public class BaseBySettingStrategy implements Strategy {
        @Autowired
        private ScfcScoreFieldValueService scoreFieldValueService;
    
        @Override
        public boolean isMatch(ScfcScoreField scoreField) {
            return ProcessFlagEnum.BASE_BY_SETTING.getCode() == scoreField.getProcessFlag();
        }
    
        @Override
        public List<ScfcScoreFieldValue> extractData(ScoreModelDimensionDTO dimensionRule) throws Exception {
            return scoreFieldValueService.getBaseFieldValueByDimension(dimensionRule);
        }
    }

    可以继续往后继续实现多个算法,这里就不一一列举。

    3. Spring Boot启动时初始化各算法

    import com.dmall.scfc.task.strategy.Strategy;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author wangxuexing
     * @descrption 加载所有抽取策略
     * @date 2019/12/4
     */
    @Configuration
    public class ExtractStrategyConfig {
        @Autowired
        private ApplicationContext applicationContext;
    
        @Bean
        public List<Strategy> pipelineProcessors() {
            Map<String, Strategy> beansOfType = applicationContext.getBeansOfType(Strategy.class);
            List<Strategy> strategies = new ArrayList<Strategy>();
            for (Strategy processService : beansOfType.values()) {
                strategies.add(processService);
            }
            return strategies;
        }
    }

    4. 基于业务场景对不同策略经行调用

    import com.dmall.dispatcher.sdk.util.IBasicExecuteContext;
    
    /**
     * @author wangxuexing
     * @descrption 数据抽取服务
     * @date 2019/12/4
     */
    public interface DataExtractService {
        /**
         * 根据具体字段抽取数据
         */
        void extractData();
    }
    /**
     * @author wangxuexing
     * @descrption 上下文调用各策略
     * @date 2019/12/4
     */
    @Slf4j
    @Service
    public class DataExtractServiceImpl implements DataExtractService {
        @Autowired
        private List<Strategy> strategyList;
        /**
         * 根据具体字段抽取数据
         */
        @Override
        public void extractData() {
            //查询所有核心企业,所有维度公式及条件
            List<ScoreModelDimensionDTO> scoreModelDimensionDTOS = scfcScoreModelDimensionService.getAllScoreModelDimensions();
            scoreModelDimensionDTOS.forEach(item -> {
                //执行不同满足匹配条件的策略
                strategyList.forEach(strategy -> {
                    extractAndInsertDataByStrategy(strategy, item);
                });
            });
        }
    
        /**
         * 根据策略抽取数据并插入
         */
        @Async//多线程异步计算插入数据
        private void extractAndInsertDataByStrategy(Strategy strategy,
                                                    ScoreModelDimensionDTO dimensionRule){
            try{
                List<Long> fieldIds = scoreFields.stream()
                        .filter(scoreField -> strategy.isMatch(scoreField))
                        .map(x->x.getId())
                        .collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(fieldIds)) {
                    dimensionRule.setScoreRuleIds(fieldIds);
                    //根据策略抽取数据
                    List<ScfcScoreFieldValue> resultList = strategy.extractData(dimensionRule);
                    if(CollectionUtils.isNotEmpty(resultList)) {
                        //设置维度ID及抓取时间
                        scoreFieldValueService.insertScoreFieldValueBatch(resultList);
                    }
                }
            } catch (Exception e) {
                log.error("根据策略"+strategy.getClass().getName()+"抽取数据失败", e);
            }
        }
    }
  • 相关阅读:
    dubbo里面的JavaBeanDescriptor是怎么进行序列化和反序列化的?
    为什么dubbo的调用重试不建议设置成超过1
    dubbo中registry、route、directory、cluster、loadbalance、route的关系以及一个引用操作和调用操作到底干了啥
    技术博客-1 DRF框架下的图片(文件)上传
    Scrum meeting 1
    beta设计和计划
    事后分析$alpha$
    项目展示$alpha$
    帮助文档
    发布声明α
  • 原文地址:https://www.cnblogs.com/barrywxx/p/12003517.html
Copyright © 2011-2022 走看看