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

【设计模式】Liskov替换原则

文章目录

      • LSP原则的定义
      • 关键点
      • 示例
      • 遵循LSP原则的示例
      • 示例2
      • 结论

Liskov替换原则(Liskov Substitution Principle,简称LSP)是面向对象设计中的五大基本原则之一,由Barbara Liskov在1987年提出。LSP原则的核心思想是: 子类对象必须能够替换掉基类对象,并且程序的行为不会发生变化。换句话说,程序中的任何地方使用基类对象时,都应该能够透明地使用其子类对象,而不影响程序的正确性。

LSP原则的定义

LSP原则可以通过以下方式定义:

如果S是T的一个子类型,那么类型为T的对象可以被类型为S的对象替换,而不会改变程序的任何性质(如正确性、任务完成能力等)。

关键点

  1. 行为一致性:子类应当保持基类的行为一致性,不应改变基类的行为。
  2. 契约(Contract)遵守:子类应当遵守基类的契约(如方法的前置条件、后置条件和不变式)。
  3. 不违反基类的约定:子类不应该违反基类中定义的约定和约束。

示例

以下是一个违反LSP原则的示例:

// 矩形
class Rectangle {
    private int width;
    private int height;

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public int getArea() {
        return width * height;
    }
}
// 正方形
class Square extends Rectangle {
    @Override
    public void setWidth(int width) {
        super.setWidth(width);
        super.setHeight(width); // 违反LSP原则
    }

    @Override
    public void setHeight(int height) {
        super.setHeight(height);
        super.setWidth(height); // 违反LSP原则
    }
}

在上述代码中,Square类继承了Rectangle类,但它违反了LSP原则,因为它改变了Rectangle类的行为。具体来说,Square类在设置宽度和高度时,强制将宽度和高度设置为相同的值,这与Rectangle类的行为不一致。

遵循LSP原则的示例

为了遵循LSP原则,可以将矩形和正方形的共同行为抽象到一个接口或抽象类中,然后分别实现这些行为:

interface Shape {
    int getArea();
}

class Rectangle implements Shape {
    private int width;
    private int height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    @Override
    public int getArea() {
        return width * height;
    }
}

class Square implements Shape {
    private int side;

    public Square(int side) {
        this.side = side;
    }

    public int getSide() {
        return side;
    }

    @Override
    public int getArea() {
        return side * side;
    }
}

在这个示例中,RectangleSquare都实现了Shape接口,并且各自定义了自己的行为。这样,RectangleSquare的行为是独立的,不会互相影响,遵循了LSP原则。

示例2

例如,假设你有一个Bird类,它有一个fly()方法。然后你创建了一个Penguin类继承自Bird,但是企鹅不会飞。在这种情况下,直接使用Penguin来替换Bird可能会导致运行时错误,因为客户代码期望所有Bird都能飞行。这违反了 LSP,因为Penguin不能安全地替换Bird。

解决这个问题的一个方法可能是重新组织你的类层次结构,比如将fly()方法移到一个新的接口Flyable中,只有能飞行的鸟类才实现这个接口。这样,Penguin就不会有fly()方法,从而避免了违反 LSP。

结论

Liskov替换原则是面向对象设计中的一个重要原则,确保子类能够替换基类而不改变程序的行为。遵循LSP原则有助于提高代码的可扩展性、可维护性和可重用性。在设计类继承关系时,务必确保子类不会违反基类的契约和行为约定,从而实现更健壮和灵活的面向对象设计。


http://www.kler.cn/news/363953.html

相关文章:

  • ChatGLM-6B大模型 + Bert预训练模型 + RAG实现知识库信息抽取(含完整代码)
  • Python入门(二)编程中的“真”与“假”,单双向选择的判断
  • 052_python基于Python高校岗位招聘和分析平台
  • Qt 二进制文件的读写
  • css模糊遮罩效果
  • ARM/Linux嵌入式面经(五二):华为
  • 智谱清言AI
  • Java | Leetcode Java题解之第497题非重叠矩形中的随机点
  • Spring AOP的概念与使用
  • 构建后端为etcd的CoreDNS的容器集群(一)、生成自签名证书
  • java的maven打包插件来了,package一键打包exe、dmg、rpm等
  • 小程序开发语言Java跟php的区别
  • Element Plus的el-tree-v2 组件实现仅叶子节点显示勾选框,并且只能单选
  • MYSQL-SQL-04-DCL(Data Control Language,数据控制语言)
  • 若依框架vue3模板
  • 单例模式是一种常见的设计模式,确保一个类只有一个实例,并提供一个全局访问点。
  • Linux Redis查询key与移除日常操作
  • 尚硅谷redis 第97节 redisTmplate下答疑
  • 代码随想录算法训练营第二天| 209.长度最小的子数组 59.螺旋矩阵II 区间和 开发商购买土地
  • 身份证识别JAVA+OPENCV+OCR
  • ref属性的作用对象类型
  • 文件操作(1) —— 文件基础知识
  • 【C++】——list 容器的解析与极致实现
  • 修改IDEA中@author变量user内容
  • 开源软件搜索工具:Reddo
  • React是如何处理事件的?