Java 违反利斯科夫'的战略模式;s替代原理

Java 违反利斯科夫'的战略模式;s替代原理,java,c#,.net,design-patterns,Java,C#,.net,Design Patterns,我正在实施策略模式,以实施不同类型鸭子的行为。代码如下: 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 flybeha

我正在实施策略模式,以实施不同类型鸭子的行为。代码如下:

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

现在我需要一门课,它有一种特殊的力量来满足门徒的愿望,比如说:

//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”中再添加一个函数,那么所有继承的成员至少需要提供一个表示“我不满足特殊愿望”的实现

在这个场景中,哪一个是更好的解决方案,在复杂的DDUCK类中添加一个方法还是扩展基类

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


我想你错过了从Duck类继承Duck的机会。它必须像- 鸭子

  • 您可以将现有方法public void GrantWishes()移动到抽象类Duck
  • 使用空定义将其设置为虚拟
  • 在复杂的DDuck类中,根据需要重写行为
  • 在SimpleDuck类中不执行任何操作
这样就不会违反替代原则。

这是一个典型的

您创建了一个基本类汽车。。。你可以预见的所有汽车都有门和轮子,还有某种类型的发动机。。。继承很有效。。。但收音机是可选的。你是做什么的?你用作文

你创建了一个名为IRadio的界面,对于每辆有收音机的汽车,你用IRadio(假设这是C#)来装饰它,这就是合成。它很容易检查一辆车是否有收音机,只要检查一下IRadio,在任何一辆有收音机的车上打开收音机都很容易


带回家的部分。在不需要它们的派生类上强制使用方法是很麻烦的。然而,在可行的情况下使一切都可组合也是一种浪费。您只需在逻辑上划清界限

策略模式是为
IFlyBehavior
提供不同的实现,而不是为
Duck
提供继承类

代码的一个问题是,
Duck
基类中有一个从未使用过的私有字段。它只能由Duck使用,因此所有继承类型都无法访问它。如果
PerformFly()
您将得到一个NullReferenceException-always。如果要继承
Duck
,可能需要在Duck的构造函数中使用IFlyBehavior


有点违背了拥有战略模式的目的,因为它强制特定的实施。我想如果你想使用一个特定的
IFlyBehavior
实现,而不是从Duck继承,你会使用composition,这可能是错误的,但是
composedduck
(如果它是一个抽象
Duck
的派生类,并且有一个方法
,你没有添加)这似乎并不违反LSP,因为它可以像任何其他鸭子一样飞行,您可以通过引用基类来使用它。谢谢。我还建议您对代码进行重新排序。从基接口和类开始。人类从上到下阅读文本(至少在英语文本的上下文中)。因此,不要使用以后定义的名称。@KozhevnikovDmitry:整个问题很复杂,Duck有GrantWishes(),它不存在于基类Duck中,甚至在其他50个派生类中,如SimpleDuck等。
public SimpleDuck(IFlybehaviour FlyBehavior){FlyBehavior=new GeneralFlyBehavior();}
-传递参数,分配给它其他的东西,不要在任何地方使用它。这没有道理。你想做什么?@user1400915,对,但是它没有违反LSP。至少在您提供的上下文中。将
GrantWiches
添加到基类不是一个好主意。这似乎违反了SRP。最好看一看桥接模式,一种类似于IWishGranter的工具。只是澄清一下,如果一辆汽车已经实现了IRadio,这是一种组合,它是否仍然被认为遵守“Liskov原则”?在我的理解中,派生类的属性或方法必须是完全可替换的,因为子类从不破坏父类类型定义,并且子类型可以替换它们的基类型。
flybehaviour = new GeneralFlybehaviour();