如何在不违反 Liskov 替换原则的情况下有效地在 类 之间共享函数
How to efficiently share functions between classes without violating the Liskov Substitution Principle
我有一个代码库,它最初是用许多不同的选项创建的,这些选项允许您让代码以稍微不同的方式执行相同的过程,如下所示:
public class MainFunction {
public void main(String option){
if (option.equals("vanilla mode")){
this.firstFunction();
}else{
this.differentVersionOfFirstFunction();
}
this.secondFunction();
}
public void firstFunction(){
//First functions code
}
public void secondFunction(){
//Second functions code
}
public void differentVersionOfFirstFunction(){
// different code from First functions code that produces the same type of end result using a slightly different method
}
}
随着各种不同选项的添加,代码变得越来越复杂。
为了解决这个问题,我最初计划创建一个 Parent object,然后可以在需要时让 children 在其 Parent 方法上有细微的不同变化.问题是我知道这会违反 Liskov 替换原则,实际上我可能有 children 应该共享相同的方法,而它们的 parent 中可能不存在。
所以我只能在相同的 class object 中使用不同的方法,以略微不同的方式完成相同的工作。
public class MainFunction {
public void main1(){
this.firstFunction();
this.secondFunction();
}
public void main2(){
this.differentVersionOfFirstFunction();
this.secondFunction();
}
public void firstFunction(){
//First functions code
}
public void secondFunction(){
//Second functions code
}
public void differentVersionOfFirstFunction(){
// different code from First functions code that produces the same type of end result using a slightly different method
}
}
我想我可以创建一个单独的实用程序 class 来容纳我所有的各种功能,但我不确定是否有更优雅的解决方案?
也许你可以尝试使用策略模式,在你的 MainFunction 中注入你每次需要使用的 Strategy 对象。看看here
我不明白你的例子是如何违反里氏替换原则的。然而,我看到的是他们可能违反了Open/Closed原则,意思是每次你需要修改你的程序时,你编辑一些MainFunction.java
文件并有一个影响 运行 程序所有可能场景的机会。更好的解决方案是拥有大量解耦的组件,这样当您需要修改某些内容时,您只需修改一小部分,这不太可能影响程序可能遇到的所有场景。这就是 单一职责原则 的意义所在。
正如另一个答案中提到的,您的场景似乎很适合应用策略模式。这可能如下所示:
- 使用
void main()
方法创建接口 MainFunction
,不带任何选项。
- 创建抽象策略 class,例如
AbstractMainFunction
和 public abstract void main()
成员,不带任何选项。此 class 将实现 MainFunction
接口。
- 根据需要创建
AbstractMainFunction
的单独实现,例如VanillaModeMainFunction
和 DifferentMainFunction
。您可能会发现在 AbstractMainFunction
. 中保留一些共享代码很有用
创建策略切换器class,例如MainFunctionService
。它将有一个方法 public void main(String option)
就像你的第一个例子一样,并且可能会有一个这样的 switch 语句:
MainFunction strategy = defaultFunction;
switch(option) {
case "vanilla":
strategy = vanillaFunction;
break;
case "different":
strategy = differentFunction;
break;
}
strategy.main();
看起来有很多事情要做,但最终您会看到这如何真正简化维护和进一步开发。
我有一个代码库,它最初是用许多不同的选项创建的,这些选项允许您让代码以稍微不同的方式执行相同的过程,如下所示:
public class MainFunction {
public void main(String option){
if (option.equals("vanilla mode")){
this.firstFunction();
}else{
this.differentVersionOfFirstFunction();
}
this.secondFunction();
}
public void firstFunction(){
//First functions code
}
public void secondFunction(){
//Second functions code
}
public void differentVersionOfFirstFunction(){
// different code from First functions code that produces the same type of end result using a slightly different method
}
}
随着各种不同选项的添加,代码变得越来越复杂。
为了解决这个问题,我最初计划创建一个 Parent object,然后可以在需要时让 children 在其 Parent 方法上有细微的不同变化.问题是我知道这会违反 Liskov 替换原则,实际上我可能有 children 应该共享相同的方法,而它们的 parent 中可能不存在。
所以我只能在相同的 class object 中使用不同的方法,以略微不同的方式完成相同的工作。
public class MainFunction {
public void main1(){
this.firstFunction();
this.secondFunction();
}
public void main2(){
this.differentVersionOfFirstFunction();
this.secondFunction();
}
public void firstFunction(){
//First functions code
}
public void secondFunction(){
//Second functions code
}
public void differentVersionOfFirstFunction(){
// different code from First functions code that produces the same type of end result using a slightly different method
}
}
我想我可以创建一个单独的实用程序 class 来容纳我所有的各种功能,但我不确定是否有更优雅的解决方案?
也许你可以尝试使用策略模式,在你的 MainFunction 中注入你每次需要使用的 Strategy 对象。看看here
我不明白你的例子是如何违反里氏替换原则的。然而,我看到的是他们可能违反了Open/Closed原则,意思是每次你需要修改你的程序时,你编辑一些MainFunction.java
文件并有一个影响 运行 程序所有可能场景的机会。更好的解决方案是拥有大量解耦的组件,这样当您需要修改某些内容时,您只需修改一小部分,这不太可能影响程序可能遇到的所有场景。这就是 单一职责原则 的意义所在。
正如另一个答案中提到的,您的场景似乎很适合应用策略模式。这可能如下所示:
- 使用
void main()
方法创建接口MainFunction
,不带任何选项。 - 创建抽象策略 class,例如
AbstractMainFunction
和public abstract void main()
成员,不带任何选项。此 class 将实现MainFunction
接口。 - 根据需要创建
AbstractMainFunction
的单独实现,例如VanillaModeMainFunction
和DifferentMainFunction
。您可能会发现在AbstractMainFunction
. 中保留一些共享代码很有用
创建策略切换器class,例如
MainFunctionService
。它将有一个方法public void main(String option)
就像你的第一个例子一样,并且可能会有一个这样的 switch 语句:MainFunction strategy = defaultFunction; switch(option) { case "vanilla": strategy = vanillaFunction; break; case "different": strategy = differentFunction; break; } strategy.main();
看起来有很多事情要做,但最终您会看到这如何真正简化维护和进一步开发。