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

2 设计模式原则之里约替换原则

一、里约替换原则

1.定义

        任何基类可以出现的地方,子类一定可以出现

        通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。

        换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法

2.具体用法

        如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。

3.代码举例

public class RectangleDemo {
    public static void main(String[] args) {
        //创建长方形对象
        Rectangle rectangle = new Rectangle();
        //设置长和宽
        rectangle.setWidth(10);
        rectangle.setLength(20);
        //扩宽与打印
        resize(rectangle);
        printLengthAndWidth(rectangle);

        System.out.println("======================");
        //创建正方形对象
        Square square = new Square();
        //设置长和宽
        square.setLength(10);
        //扩宽操作
        resize(square);
        printLengthAndWidth(square);



    }

    //扩宽方法
    public static void resize(Rectangle rectangle){
        //判断宽如果比长小,则扩宽
        while(rectangle.getWidth() <= rectangle.getLength()){
            rectangle.setWidth(rectangle.getWidth() + 1);
        }
    }

    public static void printLengthAndWidth(Rectangle rectangle){
        System.out.println(rectangle.getLength());
        System.out.println(rectangle.getWidth());
    }
}


public class Rectangle {
    private double length;
    private double width;

    public double getWidth() {
        return width;
    }

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

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }
}


public class Square extends Rectangle{
    @Override
    public void setLength(double length) {
        super.setLength(length);
        super.setWidth(length);
    }

    @Override
    public void setWidth(double width) {
        super.setLength(width);
        super.setWidth(width);
    }
}

4.案例分析

里氏替换原则的破坏点

  • 测试用例中resize 方法接受的是一个 Rectangle 对象,它的逻辑是 "如果宽度小于等于长度,就不断地扩宽"。
  • 当传入 Rectangle 对象时,这个逻辑是没问题的,最后宽度比长度大,符合预期。
  • 但是,当传入的是 Square 对象(正方形),因为 Square 重写了 setLengthsetWidth 方法,使得 lengthwidth 始终相等,导致在 resize 方法中的循环无法达到 "宽度大于长度" 的状态。

这就违背了里氏替换原则

  • RectangleSquare 是父子类关系,但是 Square 不能替代 Rectangle 使用,破坏了父类原有的行为("长方形的长和宽可以独立变化")。
  • 也就是说,resize 方法设计时假设传入的对象是标准的长方形,lengthwidth 是独立的,而 Square 强制让这两个值相等,破坏了这种假设。

解决方案

  • 不应该让 Square 继承 Rectangle,因为它们在概念上并不是 “is-a” 的关系,而是 “has-a” 的关系(正方形是特殊的四边形,不是长方形的子类)。
  • 可以重新设计类结构,让 RectangleSquare 独立存在于同一个平级层级,继承一个共同的抽象父类,如 Shape

5.总结

  • 里氏替换原则 强调子类在继承父类时,不应破坏父类原有的功能和语义。子类必须能替代父类在程序中的使用,且程序功能不会受到影响。
  • 在例子中,Square 强制让 lengthwidth 相等,破坏了 Rectangle 的语义,导致无法替代 Rectangle 使用,违反了里氏替换原则。
  • 改进方法:重新设计类结构,使 SquareRectangle 继承同一个共同的父类(如 Shape),而不是相互继承。

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

相关文章:

  • Nacos实现IP动态黑白名单过滤
  • C语言Day 04 学习总结
  • ESP32桌面天气摆件加文心一言AI大模型对话Mixly图形化编程STEAM创客教育
  • web——upload-labs——第九关——特殊字符::$DATA绕过
  • 深入理解Spring(二)
  • HBase Flink操作
  • 新华三H3CNE网络工程师认证—生成树协议
  • LeetCode:98. 验证二叉搜索树
  • 【Swift】类型标注、类型安全和类型推断
  • 【C++】友元成员
  • 给定一个数查找所在区间或者查找所有重叠区间的算法总结
  • Mac配置maven环境及在IDEA中配置Maven
  • @Autowired 和 @Resource思考(注入redisTemplate时发现一些奇怪的现象)
  • 商用密码产品认证名录说明
  • C++在实际项目中的应用第二节:C++与区块链
  • oracle初始化参数
  • Flutter:AnimatedBuilder自定义显示动画
  • mac-mini的时间机器,数据备份到alist 中的网盘
  • 山东春季高考-C语言-综合应用题
  • WPF里面的C1FlexGrid表格控件添加RadioButton单选
  • Hive离线数仓结构分析
  • 树莓派2装FreeBSD14.1 Raspberry Pi2 install FreeBSD14.1 00000121:error:0A000086:SSL
  • ✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
  • 深度学习中的正则化技术
  • C++中的组合模式
  • 「Mac玩转仓颉内测版23」基础篇3 - 深入理解整数类型