如何在不违反 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文件并有一个影响 运行 程序所有可能场景的机会。更好的解决方案是拥有大量解耦的组件,这样当您需要修改某些内容时,您只需修改一小部分,这不太可能影响程序可能遇到的所有场景。这就是 单一职责原则 的意义所在。

正如另一个答案中提到的,您的场景似乎很适合应用策略模式。这可能如下所示:

  1. 使用 void main() 方法创建接口 MainFunction,不带任何选项。
  2. 创建抽象策略 class,例如 AbstractMainFunctionpublic abstract void main() 成员,不带任何选项。此 class 将实现 MainFunction 接口。
  3. 根据需要创建 AbstractMainFunction 的单独实现,例如VanillaModeMainFunctionDifferentMainFunction。您可能会发现在 AbstractMainFunction.
  4. 中保留一些共享代码很有用
  5. 创建策略切换器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();
    

看起来有很多事情要做,但最终您会看到这如何真正简化维护和进一步开发。