当前位置: 首页 > article >正文

设计模式-离氏替换原则


离氏替换原则:全称“离散子结构替换原则”(Liskov Substitution Principle,简称LSP),是面向对象编程中的一个重要原则,由计算机科学家Barbara Liskov在1987年提出。这个原则是SOLID设计原则之一,专门用于指导类继承的使用。

离氏替换原则的核心思想是:如果S是T的一个子类,那么在任何能够使用T对象的地方都应该可以使用S对象,且程序的行为不会发生改变。

具体来说,LSP要求:

1.子类必须完全实现父类的方法和功能,不能改变父类方法的预期行为或结果。
2.子类可以扩展父类的功能,但不能削弱父类的功能或违反父类的方法签名。
3.子类替代父类时,不能抛出比父类更宽泛的异常。
实践中的应用
遵循LSP可以帮助开发者设计出更为健壮的类继承结构,避免在使用多态时出现意外行为。例如,如果子类不能在所有场景下代替父类,那么这说明子类与父类之间的继承关系可能设计不合理。

违反LSP的案例
假设我们有一个基类 Bird 和一个子类 Penguin,其中 Penguin 继承自 Bird。

public class Bird
{
    public virtual void Fly()
    {
       Debug.Log("这鸟会飞");
    }
}
public class Penguin : Bird
{
    public override void Fly()
    {
        throw new NotImplementedException("企鹅不会飞");
    }
}


在这个例子中,Bird 类有一个 Fly() 方法,假设所有的鸟都可以飞。然而,企鹅是一种不能飞的鸟,所以在 Penguin 类中,我们重写了 Fly() 方法并抛出了 NotImplementedException 异常。

违反LSP的原因:

根据LSP,Penguin 作为 Bird 的子类,应该可以在任何可以使用 Bird 对象的地方使用,而不影响程序的行为。然而,Fly() 方法在 Penguin 类中被实现为抛出异常,导致无法在期望 Bird 对象可以飞行的场景下正常使用。这显然违反了LSP,因为程序行为发生了改变。
改进后的设计
为了遵循LSP,我们可以重新设计类结构,使得 Penguin 不需要重写 Fly() 方法,或者根本不提供 Fly() 方法。我们可以引入一个接口来表示飞行能力。

public interface IFlyable
{
    void Fly();
}
public class Bird
{
   
}
public class Sparrow : Bird, IFlyable
{
    public void Fly()
    {
        Debug.Log("The sparrow is flying.");
    }
}

public class Penguin : Bird
{
    // No Fly() method here because penguins can't fly
}

IFlyable 接口仅由那些可以飞的鸟类实现,如 Sparrow,Penguin 类不实现 IFlyable 接口,因为它不能飞。这样一来,程序中的飞行能力不再与 Bird 类绑定,而是通过 IFlyable 接口分离出来,避免了不合适的继承关系。
结论
通过这种方式,我们确保了 Penguin 类不会在不能飞的情况下实现一个无意义的 Fly() 方法,避免了代码中不必要的复杂性。同时,在需要使用能够飞行的对象时,我们可以依赖 IFlyable 接口,而不必担心传入的对象无法执行飞行操作,从而更好地遵循了LSP。这个案例清楚地展示了如何通过合理的设计避免违反离氏替换原则,从而创建更健壮、灵活的代码结构。


http://www.kler.cn/a/289433.html

相关文章:

  • Ollama的安装以及大模型下载教程
  • 鸿蒙进阶篇-属性动画-animateTo转场动画
  • 【项目开发 | 跨域认证】JSON Web Token(JWT)
  • CSS 自定义滚动条样式
  • 推荐一个超漂亮ui的网页应用设计
  • 43.第二阶段x86游戏实战2-提取游戏里面的lua
  • Edge PDF 关闭 提供支持的应用Adobe Acrobat
  • 深度学习-OpenCv的运用(4)
  • 【安全生产】叉车安全带报警器有哪些特点?
  • 数分基础(06)商业分析四种类型简介
  • VsCode + Go + macOS 小白 demo运行
  • 数学建模强化宝典(9)遗传算法
  • 财富趋势金融大模型已通过备案
  • 贪心算法---合并区间
  • Flutter之CRC校验
  • python使用selenium,实现简单爬虫功能
  • 《从C/C++到Java入门指南》- 22.对象的转型
  • 机器学习面试题(9月3日笔记)
  • 跨境多账号登录如何防止IP、cookie和设备关联?
  • pil 常见用法
  • 如何打造在线音乐网站?java springboot架构,vue前端开发,音乐分享新体验
  • sealos快速搭建k8s集群
  • 记录 PyQt6 / PySide 6 自定义边框窗口的 Bug 及可能可行的解决方案:窗口抖动和添加 DWM 环绕阴影的大致原理
  • Java的IO模型详解-BIO,NIO,AIO
  • 常见接口限流算法
  • 4. 第一个3D案例—创建3D场景