之前写过一个比较基础版的策略模式,能够满足大部分使用情况,最近遇到一个业务场景,是根据不同时间段查询不同的数据集,于是乎,我就想到用策略模式的另一种实现方式来解决此问题,下面是具体代码实现,大家可以参考下这个思路解决自己遇到的类似的问题:
1.声明抽象方法
import java.util.List;
/**
* @description:声明抽象的查询方法
* @fileName: ZyCostQuery.java
* @author: Sure
* @createAt: 2023/3/14 14:40
* @updateBy: Sure
* @remark:
*/
public interface ZyCostQuery {
/**
* 声明查询方法
*/
List<CostDetailVO> queryZyCostDetail(CostQueryPageDTO costQueryPageDTO);
}
2.具体实现方法
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* @description: 具体实现1
* @fileName: ZyDataSetQuery.java
* @author: Sure
* @createAt: 2023/3/14 14:47
* @updateBy: Sure
* @remark:
*/
@Slf4j
@Service
public class ZyDataSetQuery implements ZyCostQuery {
/**
* 实现方法1
* @param costQueryPageDTO
* @return
*/
@Override
public List<CostDetailVO> queryZyCostDetail(CostQueryPageDTO costQueryPageDTO) {
}
}
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* @description: 具体实现2
* @fileName: ZyDataBaseQuery.java
* @author: Sure
* @createAt: 2023/3/14 14:46
* @updateBy: Sure
* @remark:
*/
@Slf4j
@Service
public class ZyDataBaseQuery implements ZyCostQuery {
/**
* 具体的查询方法
* @param costQueryPageDTO 查询条件
* @return
*/
@Override
public List<CostDetailVO> queryZyCostDetail(CostQueryPageDTO costQueryPageDTO) {
}
}
3.查询工厂类
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
/**
* @description: 查询工厂类
* @fileName: CostQueryFactory.java
* @author: Sure
* @createAt: 2023/3/14 14:58
* @updateBy: Sure
* @remark:
*/
@Component
public class CostQueryFactory {
/**
* 一小时的分钟数
*/
private static final long HOUR = 1 * 60 ;
private static final Map<String, ZyCostQuery> zyCostQueryMap = new HashMap<>();
static {
//数据库
zyCostQueryMap.put("ZyDataBaseQuery",new ZyDataBaseQuery());
//数据集
zyCostQueryMap.put("ZyDataSetQuery",new ZyDataSetQuery());
}
/**
* 获取具体的策略类
* @param type
* @return
*/
public static ZyCostQuery getZyCostQuery(String type) {
if (type == null || type.isEmpty()) {
throw BusinessException.build(CommonErrorCodeEnum.PARAM_EMPTY_ERROR,"type can not be null");
}
return zyCostQueryMap.get(type); }
}
到这为止,还跟之前没啥不同
重点来了
我们上面说了,要根据时间范围进入不同的策略,用if else可以实现,但是太low了,下面是一种比较完美的实现方案
4.定义过滤器用于判断进入哪个策略
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
* @description: 根据时间段区分进入哪个策略
* @fileName: ZyCostQueryFilter.java
* @author: Sure
* @createAt: 2023/3/14 15:42
* @updateBy: Sure
* @remark:
*/
@Slf4j
public class ZyCostQueryFilter {
/**
* 时间范围最小值
*/
private Long betweenMinutesMin;
/**
* 时间范围最大值
*/
private Long betweenMinutesMax;
private ZyCostQuery zyCostQuery;
/**
* 构造方法
* @param zyCostQuery
*/
public ZyCostQueryFilter(Long betweenMinutesMin,Long betweenMinutesMax, ZyCostQuery zyCostQuery) {
this.zyCostQuery = zyCostQuery;
this.betweenMinutesMin= betweenMinutesMin;
this.betweenMinutesMax=betweenMinutesMax;
}
public ZyCostQuery getZyCostQuery() {
return zyCostQuery;
}
/**
* 判断是否在范围内
* @param minutesBetween 间隔时间
* @return
*/
public boolean inRange(Long minutesBetween) {
return minutesBetween.compareTo(betweenMinutesMin)>=0 && minutesBetween.compareTo(betweenMinutesMax) <= 0;
}
}
5.定义时间范围,也就是你分策略的依据
private static final List<ZyCostQueryFilter> zyCostQueryFilters = new ArrayList<>();
/**
* 数据库最大查询时间限制(0-当前时间走数据库)
*/
private static final long DATABASEMAXHOUR = 6*60;
/**
* 数据集最大查询时间限制(上述时间到这个时间范围内走数据集)
*/
private static final long DATASETMAXHOUR = 24*60*30;
6.代码初始化
/**
* 初始化
*/
@PostConstruct
public void init() {
//加载校验对象
initZyQueryFactory();
}
/**
* 初始化查询工厂
*/
private void initZyQueryFactory() {
zyCostQueryFilters.add(new ZyCostQueryFilter(NumberUtils.LONG_ZERO,DATABASEMAXHOUR, CostQueryFactory.getZyCostQuery("ZyDataBaseQuery")));
zyCostQueryFilters.add(new ZyCostQueryFilter(DATABASEMAXHOUR,DATASETMAXHOUR, CostQueryFactory.getZyCostQuery("ZyDataSetQuery")));
}
7.代码调用
/**
* 进入不同策略的方法判断
* @param costQueryPageDTO 查询条件
* @return
*/
public List<CostDetailVO> sortQuery(CostQueryPageDTO costQueryPageDTO) {
Long minutesBetween = DateUtil.between(costQueryPageDTO.getStartDate(), costQueryPageDTO.getEndDate(), DateUnit.MINUTE);
ZyCostQuery zyCostQuery = null;
for (ZyCostQueryFilter zyCostQueryFilter : zyCostQueryFilters) {
if (zyCostQueryFilter.inRange(minutesBetween)) {
zyCostQuery = zyCostQueryFilter.getZyCostQuery();
break;
}
}
if (ObjectUtils.isEmpty(zyCostQuery)){
throw BusinessException.build(CommonErrorCodeEnum.PARAM_ILLEGAL_ERROR,"没有找到对应的查询策略");
}
return zyCostQuery.queryZyCostDetail(costQueryPageDTO);
}
版权声明:本文为GodSure0914原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。