[英]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.