战略模式违反Liskov替代原则

问题描述 投票:0回答:3

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

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();
}

这遵循“开放封闭原则”和“利斯科夫的替代原则”,我可以创造50种不同类型的鸭子,如SimpleDuckFlyingDuck等。

现在我需要一个班级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”关键字替换“:”。

java c# .net design-patterns
3个回答
2
投票

这是composition vs inheritance.的经典案例

你创造了一个基础车...所有你可预见的汽车都有门和轮子,以及一些描述的引擎......继承运作良好......但无线电是可选的。你是做什么。你用的是作文。

你创建了一个名为IRadio的接口,对于每个有收音机的汽车,你用IRadio装饰它(假设这是C#),这就是组合。它很容易检查汽车是否有收音机,只需检查IRadio,它可以轻松打开任何有RadioEnabled车的收音机。

带回家的部分。在不需要它们的派生类上强制方法是混乱的。然而,当它可以被衍生化时,使一切都可以合成也是一种浪费。你需要逻辑地绘制线条


0
投票

策略模式是关于IFlyBehavior的不同实现,而不是为Duck继承类。

您的代码的一个问题是您的Duck基类中有一个永远不会使用的私有字段。它只能由Duck​​使用,因此所有继承类型都无法访问它。如果你PerformFly()你会得到一个NullReferenceException - 总是。如果你想继承Duck,可能想要在Duck的构造函数中使用IFlyBehavior。

flybehaviour = new GeneralFlybehaviour();

有点破坏了战略模式的目的,因为它强制对其进行特定的实施。我想如果你想使用特定的IFlyBehavior实现,你可以使用组合而不是继承Duck


-3
投票

我想你只是错过了继承Duck类的ComplicatedDuck。它必须像 - ComplicatedDuck:Duck

  • 您可以将现有方法 - public void GrantWishes()移动到抽象类Duck。
  • 使用空定义使其成为虚拟。
  • 在ComplicatedDuck类中,根据需要覆盖行为。
  • 在SimpleDuck类中什么都不做。

这样就不会违反替代原则。

© www.soinside.com 2019 - 2024. All rights reserved.