设计模式七大原则 - 里氏替换原则(Liskov Substitution Principle, LSP)

里氏替换原则(Liskov Substitution Principle, LSP)

——面向对象继承体系中的“行为一致性”准则


一、定义与核心思想
  1. 核心定义
    子类对象必须能够替换父类对象,且替换后程序的逻辑行为与正确性保持不变
    即:

    • 任何父类出现的地方,子类都可透明替换(如 List list = new ArrayList() 不改变逻辑。
    • 子类可扩展父类功能,但不能修改父类原有行为(如正方形继承长方形时,修改边长计算逻辑会违反LSP。
  2. 核心思想

    • 行为一致性:子类需遵循父类定义的行为契约(方法输入输出约束)。
    • 契约式设计:父类方法的前置条件(输入约束)和后置条件(输出约束)对子类具有强制力。

二、核心内容与约束
  1. 子类对父类的行为约束

    • 不重写父类非抽象方法:若父类方法已实现,子类不应覆盖其逻辑。
    • 不强化前置条件:子类方法的输入参数条件不能比父类更严格(如父类接受 int,子类不能限为 正整数)。
    • 不弱化后置条件:子类方法的输出结果必须比父类更严格或相等(如父类返回非负整数,子类不能返回负数)。
  2. 功能扩展边界

    • 可新增方法:子类可添加特有功能(如 Bird 父类衍生 Penguin 子类新增游泳方法)。
    • 慎用继承:若子类需修改父类核心逻辑,应考虑组合替代继承。

三、优缺点分析
优点缺点
1. 增强系统健壮性:子类替换父类时行为可控。
2. 提升复用性:父类抽象稳定,子类灵活扩展。
1. 设计复杂度高:需精确划分父子类契约。
2. 过度约束:严格遵循可能限制子类灵活性。

四、应用场景
  1. 继承体系重构
    • 电商系统中,普通用户 类与 VIP用户 类的权限管理需保证行为一致。
  2. 框架扩展设计
    • Spring 的 BeanPostProcessor 接口允许子类扩展 Bean 初始化逻辑,不影响父类流程。
  3. 多态实现
    • JDK 的 List 接口与 ArrayListLinkedList 实现类间的替换。

五、反例与解决方案
  1. 反例:违反LSP的继承设计

    class Rectangle {  
        protected int width, height;  
        public void setWidth(int w) { width = w; }  
        public void setHeight(int h) { height = h; }  
    }  
    // 正方形继承长方形,重写方法违反LSP  
    class Square extends Rectangle {  
        @Override  
        public void setWidth(int w) {  
            super.setWidth(w);  
            super.setHeight(w);  // 强制宽高相等,破坏父类行为  
        }  
    }  
    

    问题Square 修改了父类行为,导致计算面积时结果异常。

  2. 解决方案:组合替代继承

    interface Shape {  
        int getArea();  
    }  
    class Rectangle implements Shape { /* 实现长方形逻辑 */ }  
    class Square implements Shape { /* 独立实现正方形逻辑 */ }  
    

    改进:消除继承依赖,通过接口定义统一行为。


六、实际案例
  1. Java集合框架
    • HashSetLinkedHashSet 遵循相同 Set 接口,替换时不影响集合操作。
  2. Android控件体系
    • TextViewButton 同为 View 子类,可互换使用且渲染逻辑一致。
  3. 支付系统扩展
    • 新增 Alipay 支付类替换 Payment 父类,不影响订单处理流程。

七、与其他原则的关系
  1. 开闭原则(OCP)
    • LSP是OCP的基础,确保子类扩展不影响父类功能。
  2. 依赖倒置原则(DIP)
    • 高层模块依赖抽象接口,子类替换时遵循LSP。
  3. 合成复用原则(CARP)
    • 当继承违反LSP时,优先使用组合替代。

总结

里氏替换原则通过约束子类行为,保障了继承体系的逻辑稳定性扩展可控性。其本质是面向对象设计中多态特性的规范化应用。实际开发中需注意:

  1. 谨慎使用继承:优先组合,必要时再继承。
  2. 契约驱动设计:明确父类方法的前后置条件,子类严格遵守。
  3. 工具辅助验证:利用单元测试检测子类是否符合LSP。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值