设计模式之模板方法实现抽奖功能

1.项目背景

接到一个需求,实现电商营销模块的圆盘抽奖功能。如果大家有关注市面上的抽奖,大致也是圆盘抽奖、九宫格抽奖,随机抽球等等。尤其是电商行业,会有各种各样的活动,因此也会出现各式各样的抽奖,那么如何更好写出抽奖模块的代码呢?基于博主涉及的业务需求,决定采用设计模式的模板方法

抽奖功能主要做几件事分别是:1.初始化奖品  2.抽奖  3.发放奖品 

那么这三件事,其实就放到模板方法的抽象类。
AbstractLotteryBaseTemplate 基础抽奖类

draw()是核心抽奖方法,里面分别调用了 executeDraw(),sendGift(),不管哪个实现类实现后,只需要调用draw()即可。具体大家可以往下看。最后会有具体调用。

/**
 * @description: 抽奖模板方法基础实现
 * @author: llk
 * @date: 2022/8/29
 */
public abstract class AbstractLotteryBaseTemplate {


    /**
     * @description: 执行抽奖
     * @author: llk
     * @date: 2022/8/29
     */
    abstract protected LotteryPrize executeDraw(Long lotteryId);

    /**
     * @description: 发放奖品
     * @author: llk
     * @date: 2022/8/29
     */
    abstract protected void sendGift(LotteryPrize lotteryPrize);

    /**
     * @description: 初始化奖品
     * @author: llk
     * @date: 2022/8/26
     */
    private void initLotteryPrize(Long lotteryId,List<LotteryPrize> lotteryPrizeList) {

        // todo

    }

    /**
     * @description: 开始抽奖
     * @author: llk
     * @date: 2022/8/26
     */
    public LotteryDrawResultServiceResp draw(Long lotteryId){

        //0.基础校验
        if(userId == null || userId == 0L){
            throw new ResultException("用户id不能为空");
        }
        if(lotteryId == null || lotteryId == 0L){
            throw new ResultException("抽奖ID不能为空");
        }
        Lottery lottery = lotteryDaoService.getById(lotteryId);
        if(lottery == null){
            throw new ResultException("不存在此抽奖活动");
        }

        //1.校验抽奖模块
        validLottery(lottery,lotteryPrizeList);

        //2.校验个人抽奖限制,如是否有权限,抽奖次数限制
        validPersonDraw(lotteryId, userId, lotteryUserCount);

        //3.初始化礼品概率队列
        initLotteryPrize(lotteryId,lotteryPrizeList);

        //4.抽奖
        LotteryPrize resultPrize = executeDraw(lotteryId);

        //5. 继续写一些核心业务,譬如抽奖次数减 1,抽奖结果入库等

        //6.发放奖品
        sendGift(lotteryPrize);

    }
}

大家可以看到 executeDraw(),sendGift()已经定义成了抽象方法,意味着这些核心关键的代码,有具体的抽奖实现类实现。因为不同的抽奖业务会有不同的规则限制和奖品发放。譬如:

圆盘抽奖:executeDraw里面的实现是用户必须下单了某商品才能抽奖。

                  sendGift里面发放的积分使我们电商系统的,直接调我们接口即可。

红包抽奖:executeDraw里面的实现是用户领了优惠券才能抽奖。

                  sendGift里面发京东卡,需要对接京东。

大家可以看到,不同的抽奖方式,两块的抽奖的内容不一样。但是初始化奖品等等,基础抽奖校验是一样的。

接下来给大家看下具体的具体后抽奖实现类。

TurntableLotteryTemplate 圆盘抽奖

/**
 * @description: 转盘抽奖
 * @author: llk
 * @date: 2022/8/29
 */
public class TurntableLotteryTemplate extends AbstractLotteryBaseTemplate{

     @Override
    protected LotteryPrize executeDraw(Long lotteryId) {

        // 校验用户必须下单了某商品才能抽奖
        return resultPrize;
    }

    @Override
    protected void sendGift(LotteryPrize lotteryPrize) {

        // 发放积分礼品
    }

​​​​​​​}
RedBagLotteryTemplate 红包抽奖
/**
 * @description: 转盘抽奖
 * @author: llk
 * @date: 2022/8/29
 */
public class TurntableLotteryTemplate extends AbstractLotteryBaseTemplate{

     @Override
    protected LotteryPrize executeDraw(Long lotteryId) {

        // 校验用户领了优惠券才能抽奖
        return resultPrize;
    }

    @Override
    protected void sendGift(LotteryPrize lotteryPrize) {

        // 发放京东卡,调京东第三方接口
    }

​​​​​​​}

最后的使用就是这样,各个抽奖方式的具体实现类直接调用draw()抽奖方法即可。


public LotteryDrawResultServiceResp draw(Long lotteryId) {

    Lottery lottery = daoService.getById(lotteryId);
    if(lottery == null){
        throw new ResultException("不存在此抽奖活动");
    }

    //具体哪个抽奖方式由开发自行去定义用哪个方式
    if(LotteryActivityTypeEnum.RED_BAG.getKey().equals(lottery.getActivityType())){
        return redBagLotteryTemplate.draw(lotteryId);
    }

    return turntableLotteryTemplate.draw(lotteryId);
}

最后,博主营销模块抽奖方式目前只有红包和圆盘,后续可能会有九宫抽奖,那么只需要实现AbstractLotteryBaseTemplate ,写自己的特殊的业务实现executeDraw(),sendGift()即可。这样就可以省略各种各样的校验等等,代码也易于维护。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值