Spring Boot 使用策略模式 + 注册表模式构建动态规则引擎

68 阅读2分钟

点击上方“程序员蜗牛g”,选择“设为星标”跟蜗牛哥一起,每天进步一点点程序员蜗牛g大厂程序员一枚 跟蜗牛一起 每天进步一点点32篇原创内容**公众号

if (user.getAge > 60 && user.getLevel() > 3) {  // 规则A} else if (...) {  // 规则B}// ...还有100多行"if地狱"

这种方式(指大量使用if-else的代码结构)扩展性差、难以测试,维护起来也头大。

此时登场:策略模式 + 注册表模式。

将这两种模式结合使用,你可以动态地插入规则,

并清晰流畅地执行它们——而无需每次都触及核心逻辑。

2.实战案例

2.1 说明

图片

关系图如下:

图片

2.2 定义Rule接口

public interface Rule<T extends ContextR> {
  /**规则名称*/  String getName() ;  /**评估规则*/  evaluate(T context) ;}

2.3 定义上下文对象

图片

public interface Context {
}

图片

public class UserContext implements Context {  private final User user ;  public UserContext(User user) {    this.user = user ;  }  public User getUser() {    return user;  }}

2.4 定义规则实现

图片

用户年龄规则

@Componentpublic class UserAgeRule implements Rule<UserContextBoolean> {  @Override  public String getName() {    return "user_age_rule";  }  @Override  public Boolean evaluate(UserContext context) {    if (context == null) {      throw new IllegalArgumentException("Context must not be null");    }    return context.getAge() > 18 ;  }}

用户等级规则

@Componentpublic class UserLevelRule implements Rule<UserContextBoolean> {  @Override  public String getName() {    return "user_level_rule";  }  @Override  public Boolean evaluate(UserContext context) {    if (context == null) {      throw new IllegalArgumentException("Context must not be null");    }    return context.getUser().getLevel() >= 3 ;  }}

辅助类

public class User {  private String name ;  private Integer age ;  private Integer level ;  // getters, setters, constructs}

2.5 定义注册表Registry

图片

@Componentpublic class RuleRegistry {  private final Map<StringRule<?, ?>> ruleStore = new HashMap<>();  public RuleRegistry(List<Rule<?, ?>> rules) {    rules.forEach(rule -> ruleStore.put(rule.getName(), rule));  }  public <T extends Context, R> R execute(String ruleName, T context) {    Rule<T, R> rule = getRuleInternal(ruleName);    return rule.evaluate(context);  }  @SuppressWarnings("unchecked")  private <T extends Context, R> Rule<T, R> getRuleInternal(String ruleName) {    Rule<?, ?> rule = ruleStore.get(ruleName);    if (rule == null) {      throw new IllegalArgumentException("Rule not found: " + ruleName);    }    return (Rule<T, R>) rule;  }}

2.6 规则调度引擎

图片

@Servicepublic class RuleEngine {  private final RuleRegistry ruleRegistry;  public RuleEngine(RuleRegistry ruleRegistry) {    this.ruleRegistry = ruleRegistry;  }  public <T extends Context, R> R execute(String ruleName, T context) {    try {      return ruleRegistry.execute(ruleName, context) ;    } catch (IllegalArgumentException e) {      throw new RuntimeException("Rule '" + ruleName + "' not found or invalid context", e);    }  }}

2.7 测试

最后,我们通过一个Controller接口进行测试。

@RestController@RequestMapping("/rules")public class RuleController {  private final RuleEngine ruleEngine;  public RuleController(RuleEngine ruleEngine) {    this.ruleEngine = ruleEngine;  }  @PostMapping("/evaluate")  public ResponseEntity<Boolean> evaluate(@RequestParam String rule, @RequestBody User user) {    UserContext context = new UserContext(user) ;    return ResponseEntity.ok(ruleEngine.execute(rule, context));  }}

测试上面的2个简单规则

图片图片

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!