【问题标题】:How to add conditions dynamically according to the different requirement?如何根据不同的需求动态添加条件?
【发布时间】:2019-11-11 07:22:48
【问题描述】:

我正在用 Java 编写代码来启用不同的组件。每个组件都需要满足一组特定条件才能启用。每个条件基本上都是一个执行一些逻辑并返回布尔值的方法。目前,我编写了一个代码,其中有一个不同的方法来为每个组件执行启用逻辑,并且相应的方法执行条件操作以返回布尔值。 我当前启用不同组件的实现如下所示:

private boolean shouldEnableComponent1() {
    String param1 = getParam1();
    String param2 = getParam2();
    String param3 = getParam3();
    if(checkCondition1(param1) && checkCondition2(param2) && checkCondition3(param3) {
       return true;
    } else {
        return false;
    }
}

private boolean shouldEnableComponent2() {
    String param1 = getParam1();
    String param2 = getParam2();
    String param4 = getParam4();
    if(checkCondition1(param1) && checkCondition2(param2) && checkCondition4(param4) {
       return true;
    } else {
        return false;
    }
}

请注意,不同的 shouldEnableComponentN() 方法可能必须调用相同的条件方法,例如在上述情况下 shouldEnableComponent1() 和 shouldEnableComponent2() 都调用 checkCondition1() 和 checkCondition2() 方法。它们的启用条件之间的区别在于第三个条件检查,即在组件 1 的情况下为 checkCondition3(),在组件2 的情况下为 checkCondition4()。
这是我能想到的最明显的实现,但它几乎没有问题 -
Duplicity - 由于不同组件的条件检查之间存在重叠,因此这部分代码是重复的。
可扩展性 - 今天有 3 个组件,明天将有 10 个组件。所以,我需要为每个组件实现 10 种不同的方法。那肯定很糟糕。

我正在考虑这个用例的策略模式,但我不确定如何在这里实现它。策略模式是正确的选择吗?如果是,请给出如何实现的高级概念,即我将在哪里放置需要跨类使用的公共变量,将所有具体类的公共逻辑部分放置在哪里等。或者是否有任何其他设计对于这个用例,哪种模式会比策略模式更好? 提前致谢

【问题讨论】:

    标签: java design-patterns strategy-pattern


    【解决方案1】:

    我想到的一个想法是为参数提供一些逻辑名称(假设它们都是您在问题中所述的字符串):

    鉴于参数集在编译时已知,您可以创建参数“注册表”:

    enum ParamName {
       PARAM1, PARAM2, PARAM3... PARAM_N;
    }
    
    class ConditionChecker {
       private Map<ParamName, Predicate<String>> registry;
    
       public ConditionChecker() {
    
            map.put(ParamName.PARAM1, this::conditionCheck1);
            map.put(ParamName.PARAM2, this::conditionCheck2);
            // populate the map with all conditions for all possible parameters 
       }
    
       // knows how to check param1
       private Boolean conditionCheck1(String param1) {
           ...
       }
    
       // knows how to check param2
       private Boolean conditionCheck2(String param2) {
          ...
       }
       ...
    
    
    }
    

    现在提供一个“通用”的条件检查方法:

     class ConditionChecker { // the same class as above, continuing...
    
    
          public boolean checkAll(Map<ParamName, String value> allParams) {
             // for each element in the map call
             for(Entry<ParamName, String> entry : allParams.entrySet()) {
                if(! registry.get(entry.getKey()).accept(entry.getValue())) {
                     return false; // at least one check failed
                 }                
             } 
             // all validations passed
             return true;
          } 
     }
    

    现在shouldEnableComponent1 拥有“应该验证哪些参数”信息,您可以执行以下操作:

    boolean shouldEnableComponent1() {
         Map<ParamName, String> paramMap = extractMapForParams(PARAM1, PARAM2, PARAM3);
         return conditionChecker.checkAll(paramMap);  
    }
    

    【讨论】:

    • 这接近我的答案,所以我的就变得多余了。但是,我建议使用稍微不同的checkAll 方法编写ConditionChecker,该方法直接采用以下形式的参数枚举常量:checkParameters(PARAM1, PARAM2, PARAM3)。这可以通过 Vararg 方法实现:public boolean checkParameters(ParamName... param) ...。如果这样做,组件的启用就变成了一条线,甚至它本身也可以有一种方法来简化它。可能很方便,因为 OP 指定了组件和条件可能会改变)。
    猜你喜欢
    • 2015-10-26
    • 2019-08-01
    • 2019-11-24
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多