• 策略模式和模板模式


    这两天学习了策略模式和模板模式,总结一下这两种模式。

    一、策略模式

    策略模式的使用场景主要是同一类行为的不同实现上,如

    • 不同类型的交易⽅式(信⽤卡、⽀付宝、微信)、
    • ⽣成唯⼀ID策略 (UUID、DB⾃增、DB+Redis、雪花算法、Leaf算法)

    策略模式主要有下面这3个类

    • 方法接口
    • 具体的多个不同实现
    • 策略选择类

    下面举一个具体的例子,在抽奖的时候,有不同的抽奖策略,下面这个例子有两个抽奖策略的实现

    1. 方法接口
    1. public interface IDrawAlgorithm {
    2. /**
    3. * SecureRandom 生成随机数,索引到对应的奖品信息返回结果
    4. *
    5. * @param strategyId 策略ID
    6. * @param excludeAwardIds 排除掉已经不能作为抽奖的奖品ID,留给风控和空库存使用
    7. * @return 中奖结果
    8. */
    9. String randomDraw(Long strategyId, List<String> excludeAwardIds);
    10. }
    1. 策略实现类
    • 策略1
    1. @Component("singleRateRandomDrawAlgorithm")
    2. public class SingleRateRandomDrawAlgorithm extends BaseAlgorithm {
    3. @Override
    4. public String randomDraw(Long strategyId, List<String> excludeAwardIds) {
    5. // 策略1实现
    6. return awardId;
    7. }
    8. }
    • 策略2
    1. @Component("entiretyRateRandomDrawAlgorithm")
    2. public class EntiretyRateRandomDrawAlgorithm extends BaseAlgorithm {
    3. @Override
    4. public String randomDraw(Long strategyId, List<String> excludeAwardIds) {
    5. // 策略2实现
    6. // 返回中奖结果
    7. return awardId;
    8. }
    9. }
    1. 策略选择类
    1. public class StrategyContext {
    2. private IDrawAlgorithm drawAlgorithm;
    3. public StrategyContext(IDrawAlgorithm drawAlgorithm) {
    4. this.drawAlgorithm = drawAlgorithm;
    5. }
    6. public String randomDraw(Long strategyId, List<String> excludeAwardIds) {
    7. return drawAlgorithm.randomDraw(strategyId, excludeAwardIds);
    8. }
    9. }

    测试:

    1. public static void main(String[] args) {
    2. StrategyContext strategyContext = new StrategyContext(new SingleRateRandomDrawAlgorithm());
    3. strategyContext.randomDraw(10001L, new ArrayList<>());
    4. }

    二、模板模式

    当一个事情可以流程化来做的时候,可以使用模板模式来开发,模版模式中有下面几个流程

    1. 定义接口
    2. 在抽象类中实现接口,并且将模板定义在抽象类中
    3. 具体的实现类继承抽象类,实现自己特有的逻辑,公共的逻辑在抽象类中实现

    下面是一个抽奖的例子,将抽奖的流程固定在模板抽象类中

    1. 定义接口
    1. public interface IDrawExec {
    2. /**
    3. * 抽奖方法
    4. * @param req 抽奖参数;用户ID、策略ID
    5. * @return 中奖结果
    6. */
    7. DrawResult doDrawExec(DrawReq req);
    8. }
    1. 在抽象类中实现接口,并且将模板定义在抽象类中

    这里面获取不在抽奖范围内的列表和执行抽奖算法步骤是包含业务逻辑的,这些可以在子类中实现,公共的放在抽象类中。

    1. public abstract class AbstractDrawBase extends DrawStrategySupport implements IDrawExec {
    2. private Logger logger = LoggerFactory.getLogger(AbstractDrawBase.class);
    3. @Override
    4. public DrawResult doDrawExec(DrawReq req) {
    5. // 1. 获取抽奖策略
    6. StrategyRich strategyRich = super.queryStrategyRich(req.getStrategyId());
    7. Strategy strategy = strategyRich.getStrategy();
    8. // 2. 校验抽奖策略是否已经初始化到内存
    9. this.checkAndInitRateData(req.getStrategyId(), strategy.getStrategyMode(), strategyRich.getStrategyDetailList());
    10. // 3. 获取不在抽奖范围内的列表,包括:奖品库存为空、风控策略、临时调整等
    11. List<String> excludeAwardIds = this.queryExcludeAwardIds(req.getStrategyId());
    12. // 4. 执行抽奖算法
    13. String awardId = this.drawAlgorithm(req.getStrategyId(), drawAlgorithmGroup.get(strategy.getStrategyMode()), excludeAwardIds);
    14. // 5. 包装中奖结果
    15. return buildDrawResult(req.getuId(), req.getStrategyId(), awardId);
    16. }
    1. 具体的实现类继承抽象类,实现自己特有的逻辑
    1. public class DrawExecImpl extends AbstractDrawBase {
    2. private Logger logger = LoggerFactory.getLogger(DrawExecImpl.class);
    3. @Override
    4. protected List<String> queryExcludeAwardIds(Long strategyId) {
    5. // 获取不在抽奖范围内的列表逻辑
    6. return awardList;
    7. }
    8. @Override
    9. protected String drawAlgorithm(Long strategyId, IDrawAlgorithm drawAlgorithm, List<String> excludeAwardIds) {
    10. // 抽奖逻辑
    11. return isSuccess ? awardId : null;
    12. }
    13. }
  • 相关阅读:
    [笔记]机器学习之机器学习理论及案例分析《二》 聚类
    Abaqus如何在后续分析步添加新的相互作用(cohesive)
    游戏合作伙伴专题:BreederDAO 与 Ultiverse 建立了一个新的元宇宙
    基于SSM的家庭理财管理系统,高质量毕业论文范例,源码,数据库脚本,论文撰写视频教程
    ROS中的图像数据
    非零基础自学Java (老师:韩顺平) 第15章 泛型 15.6 自定义泛型
    深度强化学习中Double DQN算法(Q-Learning+CNN)的讲解及在Asterix游戏上的实战(超详细 附源码)
    JNI查漏补缺(3)JNI调用java层
    相机平面与工作平面带夹角下的坐标换算
    测试用例设计方法之等效类,边界值
  • 原文地址:https://blog.csdn.net/qq_42008471/article/details/134258464