当前位置: 首页 > 知识库问答 >
问题:

用于处理复杂条件求值的设计模式

乜璞瑜
2023-03-14

我的设计是为了维护一个系统,它考虑到三个变量的值,以确定它将采取的行动。

我想重构它以使用一个设计模式,但找不到一个适合它的需要。

为了解释这种情况,我将使用一个健身房系统作为例子。

每个健身房用户都有一个合同类型,可以是:

    null
    null
  • 无限制
  • 过_65
  • 限制移动性
  • Medical_Condition
  • 低于_18

对于这三个特征的每个组合,都应该执行一组任意的操作。例如:

如果PLATINUM_MEMBERSHIP+PERSONAL_TRAINING+over_65:

    null
    null
  1. 拒绝订阅

if(任何成员资格)+STEP+medical_condition:

  1. 需要医疗批准
  2. 签名表
    null

等等。

特征的组合可以有一组动作,这些动作不是排他性的,并且不是所有的组合都得到保证。

旧代码使用嵌套开关作为实现。示例:

switch (contractType):

    case PLATINUM_MEMBERSHIP:

        switch (gymClass):            

            case (PERSONAL_TRAINING):

                switch (physicalCondition):            

                    case (OVER_65):

                        requiresMedicalApproval();
                        requiresSignedForm();

...
    null

你有什么建议?

谢谢你。

编辑:

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)优点

    null
    null

共有1个答案

夏侯渊
2023-03-14

你会有多少选择?假设每个类别有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并尝试使用命令执行包时 但我有以下错误, 我尝试了给出这里描述的类路径的不同变体,但得到了相同的错误。有人能指出我在运行程序时的错误吗?

  • 我正在为我的项目制作Netty原型。我试图在Netty之上实现一个简单的面向文本/字符串的协议。在我的管道中,我使用了以下内容: 我有一个DelimiterBaseFrameDecoder、一个字符串解码器和一个字符串编码器在管道中。 由于此设置,我的传入消息被拆分为多个字符串。这导致多次调用我的处理程序的“messageReceived”方法。这很好。但是,这需要我在内存中累积这些消息,并在收到

  • 我需要实现复杂的UI设计(老虎机的主要场景),所以我正在研究最好的方法来做到这一点。我想设计一些像商店这样的东西,当用户采取行动时,比如购买东西并按下按钮,物品移动到盒子和盒子附近。我可以从哪里开始。我想我可以使用Unity。但是我不知道C我可以使用java吗? 我是Android开发者。