Java 处理复杂条件求值的设计模式
我的设计目的是维护一个系统,该系统考虑三个变量的值,以确定将采取的行动 我想重构它以使用设计模式,但找不到适合它需要的模式 为了解释这种情况,我将以健身房系统为例 每个健身房用户都有一个类型的合同,可以是:Java 处理复杂条件求值的设计模式,java,design-patterns,refactoring,conditional,Java,Design Patterns,Refactoring,Conditional,我的设计目的是维护一个系统,该系统考虑三个变量的值,以确定将采取的行动 我想重构它以使用设计模式,但找不到适合它需要的模式 为了解释这种情况,我将以健身房系统为例 每个健身房用户都有一个类型的合同,可以是: 白金会员 黄金会员 银联会员 健身房有一些健身班: 举重 身体平衡 台阶 旋转 尊巴 个人培训 每个健身房使用者都有身体状况 无限制 65岁以上 流动性有限 医疗条件 18岁以下 对于这三个特征的每一个组合,都应该执行一组任意的操作。例如: 如果白金会员+个人培训+65岁以上:
- 白金会员
- 黄金会员
- 银联会员
- 举重
- 身体平衡
- 台阶
- 旋转
- 尊巴
- 个人培训
- 无限制
- 65岁以上
- 流动性有限
- 医疗条件
- 18岁以下
switch (contractType):
case PLATINUM_MEMBERSHIP:
switch (gymClass):
case (PERSONAL_TRAINING):
switch (physicalCondition):
case (OVER_65):
requiresMedicalApproval();
requiresSignedForm();
...
我的问题是:
- 有3个条件组合起来定义一组规则李>
- 这些规则不一定是唯一的李>
- 不是每个组合都定义了一个集合李>
编辑: 在研究@Paul的决策树方法时,我找到了一个解决方案。在使用决策树进行测试之后,我尝试使用三维数组来定义规则的条件。我还使用命令模式定义了规则激活时需要执行的操作 简言之: 1) 枚举以定义变量:
public enum TypeOfContract { ... }
public enum GymClasses { ... }
public enum PhysicalCondition { ... }
所有可能的条件都将放在枚举中
2) 用于定义操作的命令界面
public interface Command {
public void execute(Map<String, Object> parametersMap);
}
(为了在该站点中可视化而进行的异常代码格式化)
在这里,变量的有意义关联在规则三维数组中定义
这些规则是通过使用相应的枚举来定义的
对于我给出的第一个例子,白金会员+个人培训+65岁以上,以下内容适用:
RULES
[TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()]
(需要使用ordinal()返回对应于枚举位置的int)
为了表示需要执行的操作,关联了一个Procedures类,它包装了要执行的操作:
new Procedures(new RequireMedicalApproval(), new RequireSignedForm() );
RequireMedicalApproval和RequiremedignedForm都实现了命令接口
定义这种变量组合的整个过程是:
RULES
[TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()] =
new Procedures(new RequireMedicalApproval(),
new RequireSignedForm() );
要检查特定组合是否具有关联的操作,将调用loadProcedures
,传递表示该特定组合的枚举
5) 用法
Map context=newhashmap();
context.put(“userId”,123);
上下文。put(“缩写”、“C45354”);
context.put(“userDetails”,userDetails);
上下文。put(“合同类型”,合同类型。白金联盟成员资格);
上下文。put(“体操课”,体操课。个人训练);
上下文.put(“PhysicalCondition”,PhysicalCondition.OVER_65);
...
程序loadedProcedures=RulesEngine.loadProcedures(
合同类型。白金联盟成员资格,
体操课,个人训练,
身体状况(65岁以上);
for(命令操作:loadedProcedures.getActionsToExecute()){
行动。平等(上下文);
}
操作需要执行的所有信息现在都在映射中
由三个枚举表示的条件将传递给RulesEngine
RulesEngine将评估组合是否具有关联的操作,并返回一个过程对象,其中包含需要执行的这些操作的列表
如果没有(组合没有关联的操作),RulesEngine将返回一个带有空列表的有效过程对象
6) 专业人士
- 使用代码要干净得多
- 遗留代码的交换机中的代码复制现在消失了
- 这些动作现在已经标准化并得到了很好的定义(每个动作都在自己的类中)
- 现在使用的规则更容易识别(开发人员只需查看规则数组,就可以知道设置了哪些规则以及每个规则中会发生什么)
- 可以轻松添加新规则和操作
- 规则的定义很容易出错,因为规则的声明很冗长,没有进行语义分析——例如,可以接受重复,可能会覆盖以前的定义
- 现在我有了几个类,而不是嵌套在彼此内部的3个开关。维修
new Procedures(new RequireMedicalApproval(), new RequireSignedForm() );
RULES [TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()] [GymClasses.PERSONAL_TRAINING.ordinal()] [PhysicalCondition.OVER_65.ordinal()] = new Procedures(new RequireMedicalApproval(), new RequireSignedForm() );
Map<String, Object> context = new HashMap<String, Object>(); context.put("userId", 123); context.put("contractId", "C45354"); context.put("userDetails", userDetails); context.put("typeOfContract", TypeOfContract.PLATINUM_MEMBERSHIP); context.put("GymClasses", GymClasses.PERSONAL_TRAINING); context.put("PhysicalCondition", PhysicalCondition.OVER_65); ... Procedures loadedProcedures = RulesEngine.loadProcedures( TypeOfContract.PLATINUM_MEMBERSHIP, GymClasses.PERSONAL_TRAINING, PhysicalCondition.OVER_65); for (Command action : loadedProcedures.getActionsToExecute()) { action.equals(context); }