当前位置: 首页 > 知识库问答 >
问题:

如何在不违反Liskov替换原则的情况下有效地在类之间共享函数

支淮晨
2023-03-14

我有一个代码库,它最初是用许多不同的选项创建的,这些选项允许您让代码以稍微不同的方式执行相同的过程,如下所示:

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

随着各种不同选项的添加和代码变得越来越复杂,这变得越来越复杂。

为了解决这个问题,我最初计划创建一个父对象,然后在需要时,可以在父对象方法上有不同细微变化的子对象。问题是,我知道这会违反Liskov替代原则,事实上,我可能有孩子应该使用他们父母不使用的相同方法。

所以我只剩下在同一个类对象中使用不同的方法,以稍微不同的方式完成相同的工作。

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

我想我可以创建一个单独的实用程序类来保存所有的函数,但我不确定是否有更优雅的解决方案?

共有2个答案

戚学
2023-03-14

也许您可以尝试使用策略模式,在main函数中注入每次都需要使用的策略对象。看看这里

彭朝
2023-03-14

我看不出你的例子是如何违反Liskov替换原则的。然而,我看到的是,它们可能违反了打开/关闭原则,这意味着每次需要修改程序时,都要编辑一些main函数。java文件,有可能影响运行程序的所有可能情况。一个更好的解决方案是拥有大量解耦组件,这样当您需要修改某些内容时,您只修改一小部分内容,而这不太可能影响程序可能遇到的所有场景。这就是单一责任原则。

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

>

  • 使用void main()方法创建接口main函数,不带任何选项
  • 使用public abstract void main()成员创建一个抽象策略类,例如AbstractMainFunction,不带任何选项。此类将实现main函数接口
  • 根据需要创建abstractmain函数的单独实现,例如vanillamodemain函数differentmain函数。您可能会发现在abstractmain函数中保留一些共享代码非常有用
  • 创建策略切换器类,例如MainFunctionService。它将有一个方法,public void main(String选项),如第一个示例所示,并且可能会有这样一个switch语句:

    MainFunction strategy = defaultFunction;
    switch(option) {
        case "vanilla":
             strategy = vanillaFunction;
             break;
        case "different":
             strategy = differentFunction;
             break;
    }
    strategy.main();
    

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

  •  类似资料:
    • 我刚刚安装了Microsoft代码合同。这是的一部分。NET框架和Visual Studio加载项。它提供运行时检查和定义的合同的静态检查。 该工具有四个警告级别,因此我设置了最高级别。 我已经声明了违反Liskov替换原则的类。 LSP规定: 如果S是T的子类型,则T类型的对象可以替换为S类型的对象,而不改变该程序的任何期望属性 在我的例子中,违规行为是这样的:人=新孩子(23);。我们应该能够

    • 问题内容: 我的情况与Code Complete中Steve McConnell 提到的情况非常相似。我唯一的问题是基于车辆,而三轮车恰好是根据法律,属于汽车。到目前为止,汽车只有四个轮子。无论如何,我的域都不必要地复杂,因此很容易遵循下面的cats示例。 对重写例程并且在派生例程中不执行任何操作的类要保持怀疑。这通常表明基类的设计存在错误。例如,假设您有一个Cat类和一个例程Scratch(),

    • 我在一个程序中遇到了一个设计问题,这是由于一个基有一个带有一个位置(因而是可选)参数的方法。 我们假设这个类是,方法是。现在,是可选的,因为我已经知道的一些子类将使用它,其中一些不会。 实际的问题是违反Liskov替换原则:在需要的子类中,如果没有提供,我必须抛出异常,而在(未实现)中,我没有抛出任何异常例外。 的设计也很糟糕,因为我提供了一个方法,有些子类确实需要它,有些子类需要稍微不同的版本。

    • 若我将public方法添加到子类中,并且客户端程序调用added方法,则客户端程序不能使用父对象而不是子类。 这个案子违反了LSP?

    • 来自维基百科, Liskov的行为子类型概念定义了对象的可替代性概念;也就是说,如果S是T的子类型,则程序中T类型的对象可以替换为S类型的对象,而不改变该程序的任何期望属性(例如正确性)。 假设以下类层次结构: 基本抽象类-。它有一个只读属性,在后继程序中被重写。 基类的继承者-,它重写并返回灰色。 Cat的继任者-,它覆盖并返回带条纹的。 然后我们声明一个方法,参数类型为(不是)。 向该方法发送