活动时长计算尝试用Lambada 实现责任链的代码优化

活动时长计算尝试用Lambada 实现责任链的代码优化

记录下一次尝试用Lambada 来替代责任链模式下的各种接口实现的优化代码的处理。

原流程

在这里插入图片描述

原代码

主控流程


public ActivityCalcCustomerCostCheckResult calcCustomerCostCheckResult(
        ActivityCalcCustomerCostCheckResultDto dto) {
        ActivityCalcCustomerCostCheckResult result = new ActivityCalcCustomerCostCheckResult();
        //活动时长
        Integer activityDuration = dto.getActivityDuration()!=null?dto.getActivityDuration():0;
        result.setDuration(activityDuration);
        //调整后的时长
        Integer adjustedDuration = dto.getAdjustedDuration()!=null?dto.getAdjustedDuration():0;
        result.setAdjustedDuration(adjustedDuration);
        //调整的时长
        result.setAdjustDuration(adjustedDuration-activityDuration);
        //计费规则
        result.setType(dto.getChargeTypeEnum().value());
        //倍率
        result.setRate(dto.getRate);
        //标准费率时长
        Integer standardDuration = calcCustomerCostCheckStandardDuration(dto);
        result.setStandardDuration(standardDuration);
        //计算结算时长
        Integer balanceDuration = standardDuration!=null?
            calcBalanceDuration(dto.getChargeTypeEnum(),rate,standardDuration):0;
        //结算时长
        result.setBalanceDuration(balanceDuration);
        //满意度
        result.setSatisfaction(dto.getSatisfaction().value());
        //报价类型
        result.setQuoteType(dto.getQuoteType().value());
        return result;
}

计算标准费率时长子过程

/**
     * 计算客户费用核对标准时长(分钟)
     * @param dto
     * @return java.lang.Integer
     */
    private Integer calcCustomerCostCheckStandardDuration(ActivityCalcCustomerCostCheckResultDto dto) {
        if (dto.getAdjustedDuration()==null || dto.getAdjustedDuration() <=0){
            return 0;
        }
        if(dto.getServiceType()==null){
            return null;
        }
        switch (dto.getServiceType()){
            case TELEPHONE_INTERVIEW:
            case FACE_INTERVIEW:
                return calcCustomerCostCheckStandardDurationForTelephoneInterviewAndFaceInterview(dto);
            case ROADSHOW:
                return calcCustomerCostCheckStandardDurationForRoadshow(dto);
            case QUESTIONNAIRE:
                return calcCustomerCostCheckStandardDurationForQuestionnaire(dto);
            default:
                return null;
        }


    }

电访和面访活动计算标准费率时长
/**
     * 计算电话访谈和面访活动的客户标准费率结算时长
     * @param parameter
     * @return java.lang.Integer
     */
    private Integer calcCustomerCostCheckStandardDurationForTelephoneInterviewAndFaceInterview(
        ActivityCalcCustomerCostCheckResultDto parameter) {
        if(parameter.getQuoteType()==null){
            return null;
        }
        int duration = parameter.getAdjustedDuration();
        switch (parameter.getQuoteType()){
            case HOUR:
                //按小时
                if (BooleanUtils.isTrue(parameter.getIfRelationConf())) {
                    //是跟进活动 0<h<=15 -> 15
                    if (duration <= 15) {
                        return 15;
                    }else{
                        // h > 15 -> 按照实际分钟结算
                        return duration;
                    }

                }else{
                    if(BooleanUtils.isTrue(parameter.getIfTestCall())){
                        //测试活动
                        if(parameter.getTestCallLimitMinute()!=null && duration<=parameter.getTestCallLimitMinute()){
                            // h<=客户测试活动限定时长  -> 0
                            return 0;
                        }
                        // h > 客户测试活动限定时长 ->按常规活动规则计算
                    }
                    //常规活动
                    if (CustomerSatisfactionEnum.NO.equals(parameter.getSatisfaction())) {
                        //客户不满意
                        if (duration < 10L) {
                            // h <10 -> 0
                            return 0;
                        } else if (duration >= 10 && duration <= 30) {
                            // 10<=h <=30 -> 30
                            return 30;
                        } else{
                            // h > 30 -> 按照实际分钟结算
                            return duration;
                        }
                    } else {
                        //客户满意/一般
                        if(duration <= 30){
                            return 30;
                        }else{
                            // h > 30 -> 按照实际分钟结算
                            return duration;
                        }
                    }
                }

            case SCENE:
                //按场次 (电话访谈和面访暂不支持按场次计算时长)
            default:
                return null;
        }

    }

路演活动计算标准费率时长
    /**
     * 计算路演活动的客户标准费率结算时长
     * @param parameter
     * @return java.lang.Integer
     */
    private Integer calcCustomerCostCheckStandardDurationForRoadshow(
        ActivityCalcCustomerCostCheckResultDto parameter) {
        return parameter.getAdjustedDuration();
    }

问卷活动计算标准费率时长
 /**
     * 计算问卷活动的标准费率时长
     * @param parameter
     * @return java.lang.Integer
     */
    private Integer calcCustomerCostCheckStandardDurationForQuestionnaire(
        ActivityCalcCustomerCostCheckResultDto parameter) {
        return parameter.getAdjustedDuration();
    }

计算结算时长子过程

    /**
     * 计算结算时长
     * @param chargeTypeEnum
     * @param rate
     * @param duration
     * @return java.lang.Integer
     */
    private Integer calcBalanceDuration(ActivityCustomerChargeTypeEnum chargeTypeEnum,BigDecimal rate,Integer duration){
        switch (chargeTypeEnum){
            case PACKAGE_DEDUCTION:
                return rate.multiply(new BigDecimal(duration)).setScale(0, RoundingMode.CEILING).intValue();
            case FREE:
                return 0;
            case TRIAL:
            case POST_PAID:
                return duration;

        }
        return duration;
    }

新流程

新的版本需要调整活动时长计算规则,对于常规的活动标准费率计算增加了起访时长和跳档时长两个参数(其实就是把旧版的默认的这两个值是固定,调整为根据每个客户动态获取的)。并且移除了按场次 还是按时长 这两种报价形式对活动时长计算的影响。

新版本的规则流程图如下:
在这里插入图片描述

由于新版本本身就要修改这套活动时长计算代码,因此趁机对这套代码做一次重构优化,优化的思路为:
1、拆分各模式的下具体的计算规则,让各个规则独立。
2、通过用Map组合不同的计算规则
3、通过参数选择Map中不同的规则来计算处理。
4、通过一个活动时长计算上下文来解决参数传递的问题。

新代码

定义活动时长计算上下文类及相关Dto成员类型

活动时长计算上下文类
/**
 * 活动计算时长上下文
 * @author 徐明龙 XuMingLong 2022-08-04
 */
@Data @AllArgsConstructor @NoArgsConstructor @Builder
public class ActivityCalcDurationContentDto {
    
    /**
     * 活动计算时长规则配置
     */
    private ActivityCalcDurationRuleConfigDto ruleConfig;

    /**
     * 活动计算时长输入数据
     */
    private ActivityCalcDurationInputDataDto inputData;

    /**
     * 活动计算时长输出结果
     */
    private ActivityCalcDurationOutPutResultDto outPutResult;
    
    
}
活动计算时长规则配置Dto
/**
 * 活动计算时长规则配置
 */
@Data @AllArgsConstructor @NoArgsConstructor @Builder
public class ActivityCalcDurationRuleConfigDto {

    /**
     * 起访时长
     */
    private int durationOfAtLeast;

    /**
     * 跳档时长
     */
    private int durationOfEachGrade;

    /**
     * 测试活动限定时长
     */
    private Integer durationOfTestCallLimit;

}

活动计算时长输入数据Dto
/**
 * 活动计算时长输入数据
 */
@Data @AllArgsConstructor @NoArgsConstructor @Builder
public class ActivityCalcDurationInputDataDto {

    /**
     * 活动时长
     */
    private int activityDuration;

    /**
     * 调整后的时长
     */
    private int adjustedDuration;

    /**
     * 倍率
     */
    private BigDecimal rate;

    /**
     * 活动类型
     */
    private ActivityServiceTypeEnum serviceType;

    /**
     * 客户满意度
     */
    private CustomerSatisfactionEnum satisfaction;

    /**
     * 报价类型
     */
    private CustomerPricingQuoteTypeEnum quoteType;

    /**
     * 计费规则
     */
    private ActivityCustomerChargeTypeEnum chargeType;

    /**
     * 活动服务目的
     */
    private ActivityServicePurposeEnum servicePurpose;

}
活动计算时长输出结果Dto
/**
 * 活动计算时长输出结果
 * @author 徐明龙 XuMingLong 2022-08-04
 */
@Data
public class ActivityCalcDurationOutPutResultDto {

    /**
     * 活动时长
     */
    private Integer activityDuration;

    /**
     * 调整后的时长
     */
    private Integer adjustedDuration;

    /**
     * 调整的时长
     */
    private Integer adjustDuration;

    /**
     * 标准费率时长
     */
    private Integer standardDuration;

    /**
     * 结算时长
     */
    private Integer balanceDuration;

    /**
     * 倍率
     */
    private BigDecimal rate;

    /**
     * 活动类型
     */
    private ActivityServiceTypeEnum serviceType;

    /**
     * 客户满意度
     */
    private CustomerSatisfactionEnum satisfaction;

    /**
     * 报价类型
     */
    private CustomerPricingQuoteTypeEnum quoteType;

    /**
     * 计费规则
     */
    private ActivityCustomerChargeTypeEnum chargeType;

    /**
     * 活动服务目的
     */
    private ActivityServicePurposeEnum servicePurpose;

}

定义规则存储Map

    /**
     * 活动类型计算时长责任链Map
     */
    private final static Map<ActivityServiceTypeEnum, List<Function<ActivityCalcDurationContentDto,Boolean>>> calcDurationChainMap = new EnumMap<>(ActivityServiceTypeEnum.class);
    /**
     * 活动服务目的标准费率时长计算方法Map
     */
    private final static Map<ActivityServicePurposeEnum, Consumer<ActivityCalcDurationContentDto>> calcStandardDurationFunByServicePurposeMap = new EnumMap<>(ActivityServicePurposeEnum.class);
    /**
     * 客户满意度标准费率时长计算方法Map
     */
    private final static Map<CustomerSatisfactionEnum, Consumer<ActivityCalcDurationContentDto>> calcStandardDurationFunBySatisfactionMap = new EnumMap<>(CustomerSatisfactionEnum.class);

    /**
     * 活动扣费类型计算结算时长的方法Map
     */
    private final static Map<ActivityCustomerChargeTypeEnum,Consumer<ActivityCalcDurationContentDto>> calcBalanceDurationFunMap = new EnumMap<>(ActivityCustomerChargeTypeEnum.class);

各子模式的计算规则实现代码

活动计算时长上下文-预处理器
   /**
     * 预处理处理器
     */
    private final static Function<ActivityCalcDurationContentDto,Boolean> preHandler = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        ActivityCalcDurationOutPutResultDto outPutResult = new ActivityCalcDurationOutPutResultDto();
        outPutResult.setActivityDuration(inputData.getActivityDuration());
        outPutResult.setAdjustedDuration(inputData.getAdjustedDuration());
        outPutResult.setAdjustDuration(0);
        outPutResult.setStandardDuration(0);
        outPutResult.setBalanceDuration(0);
        outPutResult.setRate(inputData.getRate());
        outPutResult.setServiceType(inputData.getServiceType());
        outPutResult.setSatisfaction(inputData.getSatisfaction());
        outPutResult.setQuoteType(inputData.getQuoteType());
        outPutResult.setChargeType(inputData.getChargeType());
        outPutResult.setServicePurpose(inputData.getServicePurpose());
        contentDto.setOutPutResult(outPutResult);
        return true;
    };
常规的计算标准费率时长方法
   /**
     * 常规的计算标准费率时长方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> normalCalcStandardDurationFun= (contentDto)->{
        //获取计算规则配置
        ActivityCalcDurationRuleConfigDto ruleConfig = contentDto.getRuleConfig();
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        if(inputData.getAdjustedDuration() <=0){
            //调整后的时长小于等于0,则标准费率时长也为0
            contentDto.getOutPutResult().setStandardDuration(0);
        }else if(inputData.getAdjustedDuration() <= ruleConfig.getDurationOfAtLeast()){
            //调整后的时长<= 起访时长,标准费率时长 = 起访时长
            contentDto.getOutPutResult().setStandardDuration(ruleConfig.getDurationOfAtLeast());
        }else{
            //否则标准费率时长= 起访时长+ceil((调整后的时长-起访时长)/跳档时长)*跳档时长
            // 计算超过起访时长部分的时长
            int exceedDuration = inputData.getAdjustedDuration()-ruleConfig.getDurationOfAtLeast();
            //计算最终跳档时长
            exceedDuration = (int)Math.ceil(exceedDuration*1.0/ruleConfig.getDurationOfEachGrade())*ruleConfig.getDurationOfEachGrade();
            //计算标准费率时长
            contentDto.getOutPutResult().setStandardDuration(ruleConfig.getDurationOfAtLeast() + exceedDuration);
        }
    };
计算服务目的处理器
    /**
     * 计算服务目的处理器
     */
    private final static Function<ActivityCalcDurationContentDto,Boolean> calcServicePurposeHandler = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        if(inputData.getServicePurpose() == ActivityServicePurposeEnum.TEST){
            //获取规则配置
            ActivityCalcDurationRuleConfigDto ruleConfig = contentDto.getRuleConfig();
            //没有测试活动时长限制的配置,则测试活动自动转换为常规活动
            if(ruleConfig.getDurationOfTestCallLimit() == null ){
                inputData.setServicePurpose(ActivityServicePurposeEnum.CONVENTION);
                contentDto.getOutPutResult().setServicePurpose(inputData.getServicePurpose());
                return true;
            }
            //调整后的时长 > 客户测试活动限定时长,则转变为常规活动
            if(inputData.getAdjustedDuration() > ruleConfig.getDurationOfTestCallLimit()){
                inputData.setServicePurpose(ActivityServicePurposeEnum.CONVENTION);
                contentDto.getOutPutResult().setServicePurpose(inputData.getServicePurpose());
                return true;
            }
        }
        return true;
    };

计算调整时长处理器
    /**
     * 计算调整时长处理器
     */
    private final static Function<ActivityCalcDurationContentDto,Boolean> calcAdjustDurationHandler = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        //调整时长 = 调整后的时长 - 活动时长
        contentDto.getOutPutResult().setAdjustDuration(inputData.getAdjustedDuration()-inputData.getActivityDuration());
        return true;
    };

计算标准费率时长处理器
    /**
     * 计算标准费率时长处理器
     */
    private final static Function<ActivityCalcDurationContentDto,Boolean> calcStandardDurationHandler = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        //执行活动服务目的对应的处理方法
        calcStandardDurationFunByServicePurposeMap.get(inputData.getServicePurpose()).accept(contentDto);
        return true;
    };

测试活动计算标准费率时长方法
    /**
     * 测试活动计算标准费率时长方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcStandardDurationFunForTest = (contentDto)->{
        //测试活动的标准费率时长为0
        contentDto.getOutPutResult().setStandardDuration(0);
    };

常规活动计算标准费率时长方法
    /**
     * 常规活动计算标准费率时长方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcStandardDurationFunForConvention = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        //执行活动客户满意度对应的处理方法
        calcStandardDurationFunBySatisfactionMap.get(inputData.getSatisfaction()).accept(contentDto);
    };

跟进活动计算标准费率时长方法
    /**
     * 跟进活动计算标准费率时长方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcStandardDurationFunForRelation = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        if(inputData.getAdjustedDuration() <=0){
            //调整后的时长小于等于0,则标准费率时长也为 0
            contentDto.getOutPutResult().setStandardDuration(0);
        }else if(inputData.getAdjustedDuration() < 15){
            //调整后的时长小于15分钟,则标准费率时长= 15
            contentDto.getOutPutResult().setStandardDuration(15);
        }else{
            contentDto.getOutPutResult().setStandardDuration(inputData.getAdjustedDuration());
        }
    };

客户满意度为满意情况下的计算标准费率时长方法
    /**
     * 客户满意度为满意情况下的计算标准费率时长方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcStandardDurationFunWhenSatisfactionYes = (contentDto)->{
        //正常的标准费率时长计算处理
        normalCalcStandardDurationFun.accept(contentDto);
    };

客户满意度为一般情况下的计算标准费率时长方法
    /**
     * 客户满意度为一般情况下的计算标准费率时长方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcStandardDurationFunWhenSatisfactionCommon = (contentDto)->{
        //正常的标准费率时长计算处理
        normalCalcStandardDurationFun.accept(contentDto);
    };

客户满意度为不满意的计算标准费率时长方法
    /**
     * 客户满意度为不满意的计算标准费率时长方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcStandardDurationFunWhenSatisfactionNo = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        if(inputData.getAdjustedDuration() <=0){
            //调整后的时长小于等于0,则标准费率时长也为0
            contentDto.getOutPutResult().setStandardDuration(0);
        }else if(inputData.getAdjustedDuration() < 10){
            //调整后的时长 < 10 ,标准费率时长 = 0
            contentDto.getOutPutResult().setStandardDuration(0);
        }else {
            //正常的标准费率时长计算处理
            normalCalcStandardDurationFun.accept(contentDto);
        }
    };

计算结算时长处理器
    /**
     * 计算结算时长处理器
     */
    private final static Function<ActivityCalcDurationContentDto,Boolean> calcBalanceDurationHandler = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        //执行活动扣费类型的对应的处理方法
        calcBalanceDurationFunMap.get(inputData.getChargeType()).accept(contentDto);
        return true;
    };

套餐扣费的计算结算时长的方法
    /**
     * 套餐扣费的计算结算时长的方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcBalanceDurationFunByPackageDeduction = (contentDto)->{
        //获取输入参数
        ActivityCalcDurationInputDataDto inputData = contentDto.getInputData();
        //获取输出结果
        ActivityCalcDurationOutPutResultDto outPutResult = contentDto.getOutPutResult();
        if(outPutResult.getStandardDuration() == 0 ){
            outPutResult.setBalanceDuration(0);
        }else{
            //结算时长 = ceil(报价倍率 * 标准倍率时长)
            outPutResult.setBalanceDuration(
                inputData.getRate()
                    .multiply(new BigDecimal(outPutResult.getStandardDuration()))
                    .setScale(0, RoundingMode.CEILING)
                    .intValue()
            );
        }
    };

免费的计算结算时长的方法
    /**
     * 免费的计算结算时长的方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcBalanceDurationFunByFree = (contentDto)->{
        //免费的结算时长为0
        contentDto.getOutPutResult().setBalanceDuration(0);
    };

优惠试用的计算结算时长的方法
    /**
     * 优惠试用的计算结算时长的方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcBalanceDurationFunByTrial = (contentDto)->{
        //获取输出结果
        ActivityCalcDurationOutPutResultDto outPutResult = contentDto.getOutPutResult();
        //优惠的结算时长 = 标准费率时长
        outPutResult.setBalanceDuration(outPutResult.getStandardDuration());
    };

后付费的计算结算时长的方法
    /**
     * 后付费的计算结算时长的方法
     */
    private final static Consumer<ActivityCalcDurationContentDto> calcBalanceDurationFunByPostPaid = (contentDto)->{
        //获取输出结果
        ActivityCalcDurationOutPutResultDto outPutResult = contentDto.getOutPutResult();
        //后付费的结算时长 = 标准费率时长
        outPutResult.setBalanceDuration(outPutResult.getStandardDuration());
    };

终结处理器

目前不需要对上下文做额外的处理,保留这个是为了方便后续扩展

    /**
     * 终结处理器
     */
    private final static Function<ActivityCalcDurationContentDto,Boolean> finisherHandler = (contentDto)->{
        return true;
    };

配置规则代码

目前所有类型的活动都可以使用同一套的规则配置,以后如果业务规则修改,也可以不同的活动类型使用不同的配置。

static{
        //配置客户满意度活动标准费率计算方法
        calcStandardDurationFunBySatisfactionMap.put(CustomerSatisfactionEnum.YES,
            calcStandardDurationFunWhenSatisfactionYes);
        calcStandardDurationFunBySatisfactionMap.put(CustomerSatisfactionEnum.COMMON,
            calcStandardDurationFunWhenSatisfactionCommon);
        calcStandardDurationFunBySatisfactionMap.put(CustomerSatisfactionEnum.NO,
            calcStandardDurationFunWhenSatisfactionNo);
        //配置服务目的计算方法Map
        calcStandardDurationFunByServicePurposeMap.put(ActivityServicePurposeEnum.CONVENTION,calcStandardDurationFunForConvention);
        calcStandardDurationFunByServicePurposeMap.put(ActivityServicePurposeEnum.TEST,calcStandardDurationFunForTest);
        calcStandardDurationFunByServicePurposeMap.put(ActivityServicePurposeEnum.RELATION,
            calcStandardDurationFunForRelation);
        //配置活动扣费类型的计算方法Map
        calcBalanceDurationFunMap.put(ActivityCustomerChargeTypeEnum.PACKAGE_DEDUCTION,calcBalanceDurationFunByPackageDeduction);
        calcBalanceDurationFunMap.put(ActivityCustomerChargeTypeEnum.FREE,calcBalanceDurationFunByFree);
        calcBalanceDurationFunMap.put(ActivityCustomerChargeTypeEnum.TRIAL,calcBalanceDurationFunByTrial);
        calcBalanceDurationFunMap.put(ActivityCustomerChargeTypeEnum.POST_PAID,calcBalanceDurationFunByPostPaid);



        //配置活动的计算规则责任链
        List<Function<ActivityCalcDurationContentDto,Boolean>> calcDurationChain = List.of(
            //预处理
            preHandler,
            //计算服务目的处理器
            calcServicePurposeHandler,
            //计算调整的时长处理器
            calcAdjustDurationHandler,
            //计算标准费率时长处理器
            calcStandardDurationHandler,
            //计算结算时长处理器
            calcBalanceDurationHandler,
            //终结处理器
            finisherHandler

        );
        //配置电话访谈活动的计算时长的责任链
        calcDurationChainMap.put(ActivityServiceTypeEnum.TELEPHONE_INTERVIEW, calcDurationChain);
        //配置面访活动的计算时长的责任链
        calcDurationChainMap.put(ActivityServiceTypeEnum.FACE_INTERVIEW, calcDurationChain);
        //配置路演活动的计算时长的责任链
        calcDurationChainMap.put(ActivityServiceTypeEnum.ROADSHOW, calcDurationChain);
        //配置问卷活动的计算时长的责任链
        calcDurationChainMap.put(ActivityServiceTypeEnum.QUESTIONNAIRE, calcDurationChain);

    }

主控代码

    /**
     * 计算时长
     * @param contentDto
     * @return void
     */
    public static void calcDuration(ActivityCalcDurationContentDto contentDto){
        //获取责任链
        List<Function<ActivityCalcDurationContentDto,Boolean>> handlerChain =
            calcDurationChainMap.get(contentDto.getInputData().getServiceType());
        for(Function<ActivityCalcDurationContentDto,Boolean> handler:handlerChain){
            boolean executeNext = handler.apply(contentDto);
            if(!executeNext){
                break;
            }
        }

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值