最近系统需要对不同维度的数据进行差异化计算,也就会使用不同算法。为了以后更加容易扩展,结合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);
}
}
}
来源:https://www.cnblogs.com/barrywxx/p/12003517.html