##将发红包抽象成handler模型

发放红包是高频开发需求,将每个条件校验抽象成 handler 模型,对部分参数进行配置化,使得后面的红包需求开发量越来越少,极大提高代码复用率。使用java实现出来。

你这个想法很棒,是一个典型的规则引擎式设计 ,通过将每个发放红包的业务规则抽象成 Handler(处理器) ,实现一个可配置的、可扩展的链式校验系统。下面是一个用 Java 实现的完整思路和代码框架:


💡 设计思路

✅ 核心思想:

• 每一个"发红包"的校验条件,抽象为一个 RuleHandler。

• 使用"责任链模式"串联多个 Handler。

• 支持配置式启用某些 Handler(通过配置文件、数据库、策略中心等)。


🧱 类图结构(简化)

lua 复制代码
             +------------------+
             |  RuleHandler     | <-- 接口(抽象规则处理器)
             +------------------+
                      ▲
         +------------+-------------+
         |                          |
+-------------------+     +--------------------+
| LoginDaysHandler  |     | UserLevelHandler   | ...(具体实现类)
+-------------------+     +--------------------+

             +----------------------+
             |  RuleHandlerChain    | <-- 构建责任链 & 执行
             +----------------------+

             +----------------------+
             |  RedPacketService    | <-- 对外发放红包接口
             +----------------------+

🧩 1. 抽象 Handler 接口

arduino 复制代码
public interface RuleHandler {
    boolean handle(RedPacketContext context);
    String getName();
}

🧩 2. 示例 Handler:登录天数校验

typescript 复制代码
public class LoginDaysHandler implements RuleHandler {

    @Override
    public boolean handle(RedPacketContext context) {
        return context.getUser().getLoginDays() >= 7;
    }

    @Override
    public String getName() {
        return "LoginDaysHandler";
    }
}

🧩 3. 示例 Handler:用户等级校验

typescript 复制代码
public class UserLevelHandler implements RuleHandler {

    @Override
    public boolean handle(RedPacketContext context) {
        return context.getUser().getLevel() >= 3;
    }

    @Override
    public String getName() {
        return "UserLevelHandler";
    }
}

🧩 4. RuleHandlerChain:可配置执行链

arduino 复制代码
public class RuleHandlerChain {

    private final List<RuleHandler> handlers = new ArrayList<>();

    public RuleHandlerChain(List<RuleHandler> allHandlers, List<String> enabledHandlerNames) {
        for (RuleHandler handler : allHandlers) {
            if (enabledHandlerNames.contains(handler.getName())) {
                handlers.add(handler);
            }
        }
    }

    public boolean execute(RedPacketContext context) {
        for (RuleHandler handler : handlers) {
            if (!handler.handle(context)) {
                return false; // 某一环节失败,阻断发红包
            }
        }
        return true;
    }
}

🧩 5. 上下文类 RedPacketContext

typescript 复制代码
public class RedPacketContext {
    private final User user;
    private final Map<String, Object> params = new HashMap<>();

    public RedPacketContext(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    public Object getParam(String key) {
        return params.get(key);
    }

    public void setParam(String key, Object value) {
        params.put(key, value);
    }
}

🧩 6. 用户类(简化)

arduino 复制代码
public class User {
    private int loginDays;
    private int level;

    // constructor + getters/setters
}

🧩 7. 红包发放服务

kotlin 复制代码
public class RedPacketService {

    private final RuleHandlerChain ruleHandlerChain;

    public RedPacketService(RuleHandlerChain ruleHandlerChain) {
        this.ruleHandlerChain = ruleHandlerChain;
    }

    public boolean tryGrantRedPacket(RedPacketContext context) {
        if (ruleHandlerChain.execute(context)) {
            // 发放红包逻辑
            System.out.println("✅ 红包发放成功");
            return true;
        } else {
            System.out.println("❌ 红包发放失败,未通过规则校验");
            return false;
        }
    }
}

🔧 8. 配置方式(可来自配置中心、数据库、JSON)

ini 复制代码
public class App {

    public static void main(String[] args) {
        User user = new User();
        user.setLoginDays(10);
        user.setLevel(4);

        RedPacketContext context = new RedPacketContext(user);

        List<RuleHandler> allHandlers = List.of(
            new LoginDaysHandler(),
            new UserLevelHandler()
        );

        // 可配置的启用项
        List<String> enabledRules = List.of(
            "LoginDaysHandler",
            "UserLevelHandler"
        );

        RuleHandlerChain chain = new RuleHandlerChain(allHandlers, enabledRules);
        RedPacketService service = new RedPacketService(chain);

        service.tryGrantRedPacket(context);
    }
}

✅ 优势总结

☑️ 高复用 每个 handler 独立复用,不同活动组合即可
☑️ 易配置 支持配置开关控制规则链
☑️ 易扩展 新增规则只需添加新 handler
☑️ 易测试 每个 handler 可单测,调试方便

太好了,那我们现在来把这个「规则引擎」模块做得更像一个真正可配置、可插拔的 Spring Boot 模块,让你后续几乎零改动就能支持新的活动规则。

🚀 扩展目标

✅ 使用 Spring Boot 支持:

  1. 使用注解标记 RuleHandler

  2. 自动收集所有 RuleHandler Bean

  3. 通过配置文件控制启用哪些 handler

  4. Spring Boot Starter 风格:可独立打包复用

🧩 第一步:创建注解 @Rule

用于标记每一个 Handler 的唯一名称。

less 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component  // 让 Spring 自动扫描
public @interface Rule {
    String value();  // handler 的唯一标识
}

🧩 第二步:修改接口 RuleHandler

java 复制代码
public interface RuleHandler {
    boolean handle(RedPacketContext context);
}

❗ 不再需要 getName 方法,使用 @Rule("xxx") 代替。

🧩 第三步:示例 handler 使用注解

typescript 复制代码
@Rule("LoginDaysHandler")
public class LoginDaysHandler implements RuleHandler {

    @Override
    public boolean handle(RedPacketContext context) {
        return context.getUser().getLoginDays() >= 7;
    }
}

🧩 第四步:Handler 自动收集器 RuleHandlerFactory

收集所有 handler,并根据配置启用

kotlin 复制代码
@Component
public class RuleHandlerFactory {

    private final Map<String, RuleHandler> ruleHandlerMap = new HashMap<>();

    @Autowired
    public RuleHandlerFactory(List<RuleHandler> handlers) {
        for (RuleHandler handler : handlers) {
            Rule annotation = handler.getClass().getAnnotation(Rule.class);
            if (annotation != null) {
                ruleHandlerMap.put(annotation.value(), handler);
            }
        }
    }

    public List<RuleHandler> getHandlers(List<String> enabledRuleNames) {
        return enabledRuleNames.stream()
                .map(ruleHandlerMap::get)
                .filter(Objects::nonNull)
                .toList();
    }
}

🧩 第五步:配置文件控制规则启用

markdown 复制代码
red-packet:
  enabled-rules:
    - LoginDaysHandler
    - UserLevelHandler

对应配置类:

typescript 复制代码
@Configuration
@ConfigurationProperties(prefix = "red-packet")
public class RedPacketProperties {
    private List<String> enabledRules = new ArrayList<>();

    public List<String> getEnabledRules() {
        return enabledRules;
    }

    public void setEnabledRules(List<String> enabledRules) {
        this.enabledRules = enabledRules;
    }
}

🧩 第六步:注入规则链与服务

kotlin 复制代码
@Service
public class RedPacketService {

    private final RuleHandlerChain ruleHandlerChain;

    @Autowired
    public RedPacketService(RuleHandlerFactory factory, RedPacketProperties properties) {
        List<RuleHandler> handlers = factory.getHandlers(properties.getEnabledRules());
        this.ruleHandlerChain = new RuleHandlerChain(handlers);
    }

    public boolean tryGrantRedPacket(RedPacketContext context) {
        if (ruleHandlerChain.execute(context)) {
            System.out.println("✅ 红包发放成功");
            return true;
        } else {
            System.out.println("❌ 红包发放失败,未通过规则校验");
            return false;
        }
    }
}

✅ 最终效果

你只需要:

  1. 新增一个类,标注 @Rule("XXX")

  2. 在 application.yml 中加一句:

yaml 复制代码
red-packet:
  enabled-rules:
    - XXX

系统就能自动启用这个规则!无需改代码!

🛠️ 想做成独立模块(Starter)?

你可以将:

• @Rule 注解

• RuleHandler, RuleHandlerChain

• RedPacketProperties, RuleHandlerFactory

• 抽象服务接口

封装到一个模块 rule-engine-spring-boot-starter 中,作为一个通用"规则引擎",可用于红包、优惠券、会员推荐等场景。

相关推荐
·云扬·9 分钟前
【PmHub面试篇】PmHub 整合 TransmittableThreadLocal(TTL)缓存用户数据面试专题解析
缓存·面试·职场和发展
拉不动的猪8 小时前
TS常规面试题1
前端·javascript·面试
Joseit9 小时前
从零打造AI面试系统全栈开发
人工智能·面试·职场和发展
江城开朗的豌豆10 小时前
JavaScript篇:"闭包:天使还是魔鬼?6年老司机带你玩转JS闭包"
前端·javascript·面试
江城开朗的豌豆10 小时前
JavaScript篇:解密JS执行上下文:代码到底是怎么被执行的?
前端·javascript·面试
数据艺术家.13 小时前
Java八股文——Redis篇
java·redis·缓存·面试·nosql数据库·nosql·八股文
想用offer打牌14 小时前
面试官问我:库存预扣减之后,用户订单超时之后怎么补偿库存?我的方案让他满意...
后端·面试·架构
用户05956611920915 小时前
互联网公司校招 Java 面试题总结及答案含实操示例
java·面试
lecepin15 小时前
前端技术月刊-2025.6
前端·javascript·面试
零狐冲16 小时前
您的 ”芝士“ 外卖 《React 18》 已送达。速来领取!!!
前端·react.js·面试