违反 Liskov 替换原则的策略模式

我正在实施策略模式来实现不同类型鸭子的行为。这是代码:


public interface IFlybehaviour 

{

  public void fly();

}

public class GeneralFlybehaviour

{

  public void fly()

  {

    Console.WriteLine("I can fly as a duck");

  }

}


public abstract class Duck

{

  IFlybehaviour flybehaviour;

  Duck()

  {

  }

  public void PerformFly()

  {

   flybehaviour.fly();

  }

}


public class SimpleDuck : Duck

{

  public SimpleDuck(IFlybehaviour flybehaviour)

  {

    flybehaviour = new GeneralFlybehaviour();

  }

}


In the main method

void main()

{

  Duck d = new SimpleDuck();

  d.PerformFly();

}

这符合“开放封闭原则”和“ Liskov 替代原则”,我可以在其中创建 50 种不同类型的鸭子,例如SimpleDuck,FlyingDuck等等。


现在我需要一个ComplicatedDuck具有特殊能力的类来实现其弟子的愿望让我们说:


//public class ComplicatedDuck extends Duck (Java)

    public class ComplicatedDuck : Duck 

    {

      public ComplicatedDuck(IFlybehaviour flybehaviour)

      {

        flybehaviour = new GeneralFlybehaviour();

      }


     public void GrantWishes()

     { 

       Console.WriteLine("Wish Granted")

     }

    }

通过此更改,我们知道它违反了“Liskov 替换原则”,即该子类不会完全替换其基类。


假设如果我在“抽象类 Duck”中再添加一个函数,那么所有继承的成员至少需要提供一个实现,说明“我不授予特殊的愿望”。


在这种情况下,这是更好的解决方案,在 ComplicatedDuck 类中添加一个方法或扩展 BaseClass


注意:同样的概念适用于 Java 也只是用“implements”关键字替换“:”。


慕村9548890
浏览 170回答 3
3回答

MM们

这是组合与继承的经典案例。您创建了一辆基类汽车……所有可预见的汽车都有门和轮子,以及某种描述的引擎……继承运行良好……但收音机是可选的。你做什么工作。那么你使用组合。你创建了一个名为 IRadio 的接口,并且对于每辆有收音机的汽车,你用 IRadio 装饰它(假设这是 C#),这就是组合。检查汽车是否有收音机很容易,只需检查 IRadio,在任何有 RadioEnabled 的汽车上都可以轻松打开收音机。带回家的部分。在不需要它们的派生类上强制使用方法很麻烦。然而,在可以推导的情况下将所有东西都组合起来也是一种浪费。你只需要在逻辑上画线

隔江千里

策略模式是关于具有不同的实现,IFlyBehavior而不是关于继承Duck.您的代码的一个问题是您的Duck基类中有一个从未使用过的私有字段。它只能被 Duck 使用,因此所有继承类型都无法访问它。如果你PerformFly()会得到一个 NullReferenceException - 总是。如果你想继承Duck可能想在 Duck 的构造函数中采用 IFlyBehavior。还flybehaviour = new GeneralFlybehaviour();有点违背了拥有策略模式的目的,因为它会强制对其进行特定的实现。我想如果你想使用特定的IFlyBehavior实现,而不是从 Duck 继承,你会使用组合

拉莫斯之舞

我认为您只是错过了从 Duck 类继承 ComplicatedDuck。它必须像 - ComplicatedDuck : Duck您可以将现有方法 - public void GrantWishes() 移动到抽象类 Duck。使用空定义使其成为虚拟。在 ComplicatedDuck 类中,根据需要覆盖行为。在 SimpleDuck 类中什么都不做。这样就不会违反替代原则。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java