【设计模式】Liskov替换原则

文章目录

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

LSP原则的定义

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

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

关键点

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

示例

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

java 复制代码
// 矩形
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原则,可以将矩形和正方形的共同行为抽象到一个接口或抽象类中,然后分别实现这些行为:

java 复制代码
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原则有助于提高代码的可扩展性、可维护性和可重用性。在设计类继承关系时,务必确保子类不会违反基类的契约和行为约定,从而实现更健壮和灵活的面向对象设计。

相关推荐
清风-云烟7 小时前
使用redis-cli命令实现redis crud操作
java·linux·数据库·redis·spring·缓存·1024程序员节
Joeysoda12 小时前
Java数据结构 (链表反转(LinkedList----Leetcode206))
java·linux·开发语言·数据结构·链表·1024程序员节
比特在路上16 小时前
StackOrQueueOJ3:用栈实现队列
c语言·开发语言·数据结构·1024程序员节
0xCC说逆向2 天前
Windows图形界面(GUI)-QT-C/C++ - Qt键盘与鼠标事件处理详解
c语言·开发语言·c++·windows·qt·win32·1024程序员节
明明真系叻4 天前
2025.1.18机器学习笔记:PINN文献精读
人工智能·笔记·深度学习·机器学习·1024程序员节
0xCC说逆向4 天前
Windows图形界面(GUI)-QT-C/C++ - Qt List Widget详解与应用
c语言·开发语言·c++·windows·qt·win32·1024程序员节
明明真系叻6 天前
2025.1.12机器学习笔记:GAN文献阅读
人工智能·笔记·深度学习·机器学习·1024程序员节
比特在路上7 天前
OJ12:160. 相交链表
c语言·数据结构·算法·链表·1024程序员节
earthzhang20218 天前
《深入浅出HTTPS》读书笔记(28):DSA数字签名
开发语言·网络协议·算法·https·1024程序员节
比特在路上9 天前
初阶数据结构【栈及其接口的实现】
c语言·开发语言·数据结构·1024程序员节