OptaPlanner辅祭排班开发中Drools评分计算的泛型类型问题
解决Drools中用
AbstractMap.SimpleImmutableEntry替代自定义请求类的泛型问题 我之前在优化OptaPlanner排班规则时也碰到过类似的泛型匹配坑,用通用Entry类替代自定义请求类确实能减少重复代码,但Drools的规则引擎对泛型的自动推断确实不太灵光。给你几个实用的解决方案,按推荐程度排序:
1. 显式添加类型检查约束(最直接)
Drools不会自动识别SimpleImmutableEntry的泛型参数,所以在规则里直接通过instanceof明确限定键值的类型,模拟原来自定义类的结构即可。比如针对你的两种请求场景:
处理DateOffRequest逻辑的规则
rule "Penalize Date Off Request Violation" when // 明确限定Entry的key是Server,value是LocalDate $dateOffReq : AbstractMap.SimpleImmutableEntry( key instanceof Server, value instanceof LocalDate ) // 关联对应的Server和排班Shift $server : Server(this == $dateOffReq.key) $conflictingShift : Shift(date == $dateOffReq.value, server == $server) then // 执行评分惩罚 scoreHolder.addHardConstraintMatch(kcontext, -10); end
处理DayOffRequest逻辑的规则
rule "Penalize Day Off Request Violation" when $dayOffReq : AbstractMap.SimpleImmutableEntry( key instanceof Server, value instanceof DayOfWeek ) $server : Server(this == $dayOffReq.key) $conflictingShift : Shift(dayOfWeek == $dayOffReq.value, server == $server) then scoreHolder.addHardConstraintMatch(kcontext, -10); end
2. 用类型别名简化代码(可选优化)
如果觉得每次写AbstractMap.SimpleImmutableEntry太冗长,可以在规则文件开头定义别名,让代码更清爽:
// 定义类型别名,后续规则里直接用RequestEntry declare AbstractMap.SimpleImmutableEntry as RequestEntry end
之后的规则就可以用RequestEntry代替全称,类型检查逻辑保持不变。
3. 给请求加类型标记(避免混淆场景)
如果担心不同类型的Entry在规则里被误匹配,可以给Entry的key增加一个请求类型标记,比如用枚举区分:
// 定义请求类型枚举 enum RequestType { DATE_OFF, DAY_OFF } // 创建DateOff请求时 new AbstractMap.SimpleImmutableEntry<>( new Pair<>(server, RequestType.DATE_OFF), localDate ); // 创建DayOff请求时 new AbstractMap.SimpleImmutableEntry<>( new Pair<>(server, RequestType.DAY_OFF), dayOfWeek );
对应的规则可以同时匹配类型标记和值类型:
rule "Date Off Violation" when $req : RequestEntry( key.value == RequestType.DATE_OFF, value instanceof LocalDate ) $server : Server(this == $req.key.key) $shift : Shift(date == $req.value, server == $server) then // 惩罚逻辑 end
这种方式更清晰,适合请求类型较多的场景。
总结
最推荐第一种方案,用显式的类型检查让Drools正确识别泛型边界,既简化了Java端的重复类定义,又能保证规则的准确性。如果追求代码更简洁,可以搭配类型别名一起用。
内容的提问来源于stack exchange,提问作者Martin Kröning
相关产品推荐
相关产品推荐

