在决定调用哪个方法时如何避免 if..else(或任何条件)?
How to avoid if..else(or any conditionals) while deciding which method to be called?
在静态类型语言中,如何在不违反 LSP 的情况下遵循开闭原则来决定使用不同的参数调用哪个方法?
考虑
这样的要求
操作一:对Table1
执行数据库操作
动作2:根据输入
对Table2进行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 语句的主体移动到方法并维护以操作作为名称的键映射,想出了一种在上面的代码中遵循 OCP 以执行其他操作的方法。 Reference
但是感觉解决方案违反了 OCP,因为包装第一个 if 块内容的方法将不会接收任何参数,而包装第二个 if 块内容的第二个方法将有一个参数。
它要么强制所有方法在遵循 OCP 但违反 LSP 的权衡中遵循相同的签名,要么放弃 OCP 本身,从而使用多个 if 语句。
一个简单的解决方案是定义一个策略,该策略执行当前包含在 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);
}
}
}
不幸的是,您认识到的权衡是在 Java、C++、C# 等中使用 OOP 时必须处理的问题,因为系统是动态组合在一起的,而 SOLID 可以解决这些缺陷。但是 SOLID 原则旨在提供指导,我不会惯用地遵循它们。
我希望能找到比我更好的程序员的例子来说明命令模式。但我只是发现了非常糟糕的例子,这些例子并没有真正解决你的问题。
定义将意图(定义为字符串或枚举,单击按钮)与动作(对象,lambda 函数)相关联的问题将始终需要我们必须处理的间接级别。一些抽象层是可以接受的,例如:永远不要直接在视图中调用模型或服务。您还可以考虑实施事件调度程序和相应的侦听器,这将有助于松散耦合。但是在较低的级别上,您必须查找所有听众 ...
obj 的性质不明确,但我建议使用 well-defined 接口并在整个代码中传递它,其中接口的 class 实现等同于 'action'.这是一个在 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
}
}
如果这不符合您的要求,请随时联系 :)
在静态类型语言中,如何在不违反 LSP 的情况下遵循开闭原则来决定使用不同的参数调用哪个方法?
考虑
这样的要求操作一:对Table1
执行数据库操作动作2:根据输入
对Table2进行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 语句的主体移动到方法并维护以操作作为名称的键映射,想出了一种在上面的代码中遵循 OCP 以执行其他操作的方法。 Reference
但是感觉解决方案违反了 OCP,因为包装第一个 if 块内容的方法将不会接收任何参数,而包装第二个 if 块内容的第二个方法将有一个参数。
它要么强制所有方法在遵循 OCP 但违反 LSP 的权衡中遵循相同的签名,要么放弃 OCP 本身,从而使用多个 if 语句。
一个简单的解决方案是定义一个策略,该策略执行当前包含在 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);
}
}
}
不幸的是,您认识到的权衡是在 Java、C++、C# 等中使用 OOP 时必须处理的问题,因为系统是动态组合在一起的,而 SOLID 可以解决这些缺陷。但是 SOLID 原则旨在提供指导,我不会惯用地遵循它们。
我希望能找到比我更好的程序员的例子来说明命令模式。但我只是发现了非常糟糕的例子,这些例子并没有真正解决你的问题。
定义将意图(定义为字符串或枚举,单击按钮)与动作(对象,lambda 函数)相关联的问题将始终需要我们必须处理的间接级别。一些抽象层是可以接受的,例如:永远不要直接在视图中调用模型或服务。您还可以考虑实施事件调度程序和相应的侦听器,这将有助于松散耦合。但是在较低的级别上,您必须查找所有听众 ...
obj 的性质不明确,但我建议使用 well-defined 接口并在整个代码中传递它,其中接口的 class 实现等同于 'action'.这是一个在 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
}
}
如果这不符合您的要求,请随时联系 :)