簡體   English   中英

在決定調用哪個方法時如何避免 if..else(或任何條件)?

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

如何在不違反 LSP 的情況下遵循 Open Close 原則,同時決定在靜態類型語言中使用不同參數調用哪個方法?

考慮這樣的要求

  • 動作一:對表1進行DB操作

  • 動作2:根據輸入對表2進行DB操作

  • 行動 3:什么都不做

上述要求的代碼看起來像

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
    }
}

通過將 if 語句的主體移動到方法並維護以操作為名稱的鍵的 map,找到了一種在上述代碼中遵循 OCP 以執行其他操作的方法。 參考

但是感覺解決方案違反了 OCP,因為包裝第一個 if 塊內容的方法不會接收任何參數,第二種包裝第二個 if 塊內容的方法將有一個參數。

要么強制所有方法遵循相同的簽名以權衡 OCP 但違反 LSP,要么放棄 OCP 本身,從而使用多重 if 語句。

翻轉。 讓 object 定義行為,而不是過程。

現在,符合父 class 的對象集合可以調用 Update() 並執行適當的操作,而無需檢查類型。

ParentClass {
    Update() {}
}

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

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

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

一個簡單的解決方案是定義一個策略,該策略執行當前包含在if / else if / else分支中的代碼:

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

需要注冊的策略:

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);
    }
  }
}

obj 的性質是模棱兩可的,但我建議使用定義明確的接口並將其傳遞到整個代碼中,其中接口的 class 實現等同於您的“操作”。 以下是 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
  }
}

如果這不符合您的要求,請隨時聯系:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM