简体   繁体   English

在决定调用哪个方法时如何避免 if..else(或任何条件)?

[英]How to avoid if..else(or any conditionals) while deciding which method to be called?

How to follow Open Close Principle without violating LSP while deciding which method to be invoked with different parameters in a statically typed language?如何在不违反 LSP 的情况下遵循 Open Close 原则,同时决定在静态类型语言中使用不同参数调用哪个方法?

Consider the requirement like考虑这样的要求

  • Action 1: perform DB operation on Table 1动作一:对表1进行DB操作

  • Action 2: Perform DB operation on Table 2 based on input动作2:根据输入对表2进行DB操作

  • Action 3: Do Nothing行动 3:什么都不做

Code for above requirement would look like上述要求的代码看起来像

process(obj) {
    
    if(obj.type === action1) {
       db.updateTable1()
    }
    if(obj.type === action2) {
       db.updateTable2(obj.status)
    }
    if(obj.type === action3) {
       //May be log action 3 recieved
    }
}

Figured out a way to follow OCP in above code for additional actions, by moving body of if statement to method and maintain a map of keys with action as name.通过将 if 语句的主体移动到方法并维护以操作为名称的键的 map,找到了一种在上述代码中遵循 OCP 以执行其他操作的方法。 Reference参考

However feels solution is violating the OCP as method wrapping the contents of first if block will not receive any parameter, second method wrapping the contents of second if block will have a parameter.但是感觉解决方案违反了 OCP,因为包装第一个 if 块内容的方法不会接收任何参数,第二种包装第二个 if 块内容的方法将有一个参数。

Either it forces all method to follow the same signature in trade off following OCP but violating LSP or give up OCP itself and thereby live with multi if statements.要么强制所有方法遵循相同的签名以权衡 OCP 但违反 LSP,要么放弃 OCP 本身,从而使用多重 if 语句。

Flip it.翻转。 Make the object define the behaviour, not the process.让 object 定义行为,而不是过程。

Now, a collection of objects conforming to the parent class can call Update() and perform an appropriate action without checking the type.现在,符合父 class 的对象集合可以调用 Update() 并执行适当的操作,而无需检查类型。

ParentClass {
    Update() {}
}

Class1 : ParentClass {
    Update() {
        db.updateTable1()
    }
}

Class2 : ParentClass {
    Update() {
        db.updateTable2(class2.status)
    }
}

Class3 : ParentClass {
    Update() { 
        // do nothing
    }
}

A simple solution would be to define a strategy, which execute the code currently contained in the if / else if / else branches:一个简单的解决方案是定义一个策略,该策略执行当前包含在if / else if / else分支中的代码:

interface Strategy {
  String getType();
  void apply();
}

The strategies need to be registered:需要注册的策略:

class Executor {
  private Map<String, Strategy> strategies;

  void registerStrategy(strategy Strategy) {
    strategies.put(strategy.getType(), strategy);
  }

  void process(obj) {
    if (strategies.containsKey(obj.type)) {
      // apply might execute db.updateTable1(),
      // depending on the interface's implementation
      strategies.get(obj.type).apply();
    } else {
      System.out.println("No strategy registered for type: " + obj.type);
    }
  }
}

The nature of obj is ambiguous, but I would recommend having a well-defined interface and pass it throughout your code where the class implementation of your interface would be equivalent to your 'action'. obj 的性质是模棱两可的,但我建议使用定义明确的接口并将其传递到整个代码中,其中接口的 class 实现等同于您的“操作”。 Here's an example of what that might look like in Typescript:以下是 Typescript 中的示例:

interface someDBInterface {
  performAction() : void;
}

function process(obj : someDBInterface) {
  let result = obj.performAction();
}

class action1 implements someDBInterface {
  status: any
  performAction() {
    //db.updateTable1();
  }
}

class action2 implements someDBInterface {
  status : any
  performAction() {
    //db.updateTable1(this.status);
  }
}

class action3 implements someDBInterface {
  performAction() {
    //May be log action 3 recieved
  }
}

If this doesn't meet your requirements, feel free to reach out:)如果这不符合您的要求,请随时联系:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM