为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕村9548890 2021-09-15 14:22:52
我正在实施策略模式来实现不同类型鸭子的行为。这是代码: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 methodvoid 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”关键字替换“:”。
查看完整描述

3 回答

?
MM们

TA贡献1886条经验 获得超2个赞

这是组合与继承的经典案例

您创建了一辆基类汽车……所有可预见的汽车都有门和轮子,以及某种描述的引擎……继承运行良好……但收音机是可选的。你做什么工作。那么你使用组合。

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

带回家的部分。在不需要它们的派生类上强制使用方法很麻烦。然而,在可以推导的情况下将所有东西都组合起来也是一种浪费。你只需要在逻辑上画线


查看完整回答
反对 回复 2021-09-15
?
隔江千里

TA贡献1906条经验 获得超10个赞

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

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

flybehaviour = new GeneralFlybehaviour();

有点违背了拥有策略模式的目的,因为它会强制对其进行特定的实现。我想如果你想使用特定的IFlyBehavior实现,而不是从 Duck 继承,你会使用组合


查看完整回答
反对 回复 2021-09-15
?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

我认为您只是错过了从 Duck 类继承 ComplicatedDuck。它必须像 - ComplicatedDuck : Duck

  • 您可以将现有方法 - public void GrantWishes() 移动到抽象类 Duck。

  • 使用空定义使其成为虚拟。

  • 在 ComplicatedDuck 类中,根据需要覆盖行为。

  • 在 SimpleDuck 类中什么都不做。

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


查看完整回答
反对 回复 2021-09-15
  • 3 回答
  • 0 关注
  • 169 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信