結合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);
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM