策略模式(进阶版)

33 篇文章 1 订阅

之前写过一个比较基础版的策略模式,能够满足大部分使用情况,最近遇到一个业务场景,是根据不同时间段查询不同的数据集,于是乎,我就想到用策略模式的另一种实现方式来解决此问题,下面是具体代码实现,大家可以参考下这个思路解决自己遇到的类似的问题:

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);
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值