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

时间:2018-09-12 03:30:22

标签: 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 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种不同类型的鸭子,例如SimpleDuck,{ {1}}等。

现在我需要一个FlyingDuck类,在该类中,它具有赋予其门徒愿望的特殊权力,可以说:

ComplicatedDuck

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

假设如果我在“抽象类鸭子” 中添加了一个功能,那么所有继承的成员至少需要提供一个实现,说“我不给予特别的祝福”。

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

  

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

2 个答案:

答案 0 :(得分:2)

这是composition vs inheritance.

的经典案例

您创建了一个基础类汽车...您所有可预见的汽车都有门和轮子,并且有某种描述的引擎...继承运行良好...但是收音机是可选的。你是做什么。好吧,你使用合成。

您创建一个名为IRadio的接口,对于每辆有收音机的汽车,都使用IRadio(假设这是C#)进行装饰,即组成。它很容易检查汽车是否装有收音机,只需检查IRadio即可轻松地在任何装有RadioEnabled的汽车中打开收音机。

带回家。在不需要它们的派生类上强制使用方法是很麻烦的。然而,在一切都可行的情况下使一切都变得可组合也是浪费。您只需要逻辑地画线

答案 1 :(得分:0)

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

代码的一个问题是,您的Duck基类中有一个私有字段,从未使用过。它只能由Duck​​使用,因此所有继承类型都不能访问它。如果您PerformFly(),将始终收到NullReferenceException。如果您想继承Duck,则可能想在Duck的构造函数中使用IFlyBehavior。

flybehaviour = new GeneralFlybehaviour();

有点失败,因为它具有强制实施特定策略的策略模式的目的。我想如果要使用特定的IFlyBehavior实现,而不是从Duck继承