我的设计是为了维护一个系统,它考虑到三个变量的值,以确定它将采取的行动。
我想重构它以使用一个设计模式,但找不到一个适合它的需要。
为了解释这种情况,我将使用一个健身房系统作为例子。
每个健身房用户都有一个合同类型,可以是:
对于这三个特征的每个组合,都应该执行一组任意的操作。例如:
如果PLATINUM_MEMBERSHIP+PERSONAL_TRAINING+over_65:
if(任何成员资格)+STEP+medical_condition:
等等。
特征的组合可以有一组动作,这些动作不是排他性的,并且不是所有的组合都得到保证。
旧代码使用嵌套开关作为实现。示例:
switch (contractType):
case PLATINUM_MEMBERSHIP:
switch (gymClass):
case (PERSONAL_TRAINING):
switch (physicalCondition):
case (OVER_65):
requiresMedicalApproval();
requiresSignedForm();
...
你有什么建议?
谢谢你。
编辑:
public enum TypeOfContract { ... }
public enum GymClasses { ... }
public enum PhysicalCondition { ... }
public interface Command {
public void execute(Map<String, Object> parametersMap);
}
public class Procedures {
private List<Command> actionsToExecute = new LinkedList<Command>();
public static final Procedures NO_ACTIONS_TO_EXECUTE = new Procedures();
private Procedures() {}
public Procedures(Command... commandsToExecute) {
if (commandsToExecute == null || commandsToExecute.length == 0) {
throw new IllegalArgumentException("Procedures must have at least a command for execution.");
}
for (Command command : commandsToExecute) {
actionsToExecute.add(command);
}
}
public List<Command> getActionsToExecute() {
return Collections.unmodifiableList(this.actionsToExecute);
}
}
如果三个变量的组合不存在,它将发送NO_ACTIONS_TO_EXECUTE而不是null。
4)RulesEngine类,用于注册规则及其命令
public class RulesEngine {
private static final int NUMBER_OF_FIRST_LEVEL_RULES = TypeOfContract.values().length;
private static final int NUMBER_OF_SECOND_LEVEL_RULES = GymClasses.values().length;
private static final int NUMBER_OF_THIRD_LEVEL_RULES = PhysicalCondition.values().length;
private static final Procedures[][][] RULES =
new Procedures[NUMBER_OF_FIRST_LEVEL_RULES]
[NUMBER_OF_SECOND_LEVEL_RULES]
[NUMBER_OF_THIRD_LEVEL_RULES];
{ //static block
RULES
[TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()] =
new Procedures(new RequireMedicalApproval(),
new RequireSignedForm() );
RULES
[TypeOfContract.GOLD_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()] =
new Procedures(new RequireMedicalApproval(),
new RequireSignedForm(),
new AddExtraMonthlyFee() );
...
}
private RulesEngine() {}
public static Procedures loadProcedures(TypeOfContract TypeOfContract,
GymClasses GymClasses, PhysicalCondition PhysicalCondition) {
Procedures procedures = RULES
[TypeOfContract.ordinal()]
[GymClasses.ordinal()]
[PhysicalCondition.ordinal()];
if (procedures == null) {
return Procedures.NO_ACTIONS_TO_EXECUTE;
}
return procedures;
}
}
(为了在此站点中的可视化而进行的异常代码格式设置)
RULES
[TypeOfContract.PLATINUM_MEMBERSHIP.ordinal()]
[GymClasses.PERSONAL_TRAINING.ordinal()]
[PhysicalCondition.OVER_65.ordinal()]
为了表示需要执行的操作,将关联一个Procedures类,包装要执行的操作:
new Procedures(new RequireMedicalApproval(), new RequireSignedForm() );
RequireMedicalApproval和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);
}
操作需要执行的所有信息现在都在映射中。
由三个枚举表示的条件被传递给RulesEngine。
RulesEngine将评估组合是否有关联的操作,并且它将返回一个Procedures对象,其中包含需要执行的这些操作的列表。
如果不是(组合没有与之关联的操作),RulesEngine将返回一个有效的Procedures对象,其中包含一个空列表。
6)优点
你会有多少选择?假设每个类别有8位,也许你可以把一个特定的组合表示为一个24位的数字,每个类别有8位。当您收到一组选项时,将其转换为一个位模式,然后根据位掩码将和
转换为一个位模式,以确定是否需要执行某个操作。
这仍然需要您执行测试,但至少它们不是嵌套的,并且您只需要在添加新特性时添加一个新的测试。
我有一个离散事件流进入我的系统,我需要根据每个事件的内容应用规则。另外,我想对这些流事件应用复杂的事件处理。 约束1.这些规则是用户提供的,并将动态更改。2.每当应用规则时,我不想重新启动我的系统。3.HA 4.只有成熟的开源解决方案 可能的方式...1.在Storm螺栓内运行Esper CEP 2。让口水流到Storm螺栓里 > 这会处理单事件规则和复杂事件吗?规则更改是否需要我的Storm重新
我有一个flink cep代码,可以从套接字读取数据并检测模式。假设模式(单词)为“警报”。如果单词alert出现五次或五次以上,则应创建一个警报。但我得到了一个输入不匹配错误。Flink版本为1.3.0。提前谢谢!!
什么是 Nutz.Dao 中的复杂SQL条件 对于 Nutz.Dao 来说,它本质上就是将你的 Java 对象转化成 SQL,然后交给 JDBC 去执行。 而 SQL 中,当执行数据删除和查询操作时,最常用的就是 WHERE 关键字。 WHERE 关键字后面的就是所谓的复杂查询条件 Nutz.Dao 将如何如何使用这个条件 Dao 接口的 clear 方法和 query 方法的第二个参数,就是为了
我正在尝试了解Apache Flink CEP程序,该程序用于监控数据中心中的机架温度,如Flink官方文档所述。但是当我按照步骤使用mvn clean package创建jar并尝试使用命令执行包时 但我有以下错误, 我尝试了给出这里描述的类路径的不同变体,但得到了相同的错误。有人能指出我在运行程序时的错误吗?
我需要实现复杂的UI设计(老虎机的主要场景),所以我正在研究最好的方法来做到这一点。我想设计一些像商店这样的东西,当用户采取行动时,比如购买东西并按下按钮,物品移动到盒子和盒子附近。我可以从哪里开始。我想我可以使用Unity。但是我不知道C我可以使用java吗? 我是Android开发者。
我正在为我的项目制作Netty原型。我试图在Netty之上实现一个简单的面向文本/字符串的协议。在我的管道中,我使用了以下内容: 我有一个DelimiterBaseFrameDecoder、一个字符串解码器和一个字符串编码器在管道中。 由于此设置,我的传入消息被拆分为多个字符串。这导致多次调用我的处理程序的“messageReceived”方法。这很好。但是,这需要我在内存中累积这些消息,并在收到