首页 > 其他分享 >【原理篇】软件设计原则之里氏代换原则

【原理篇】软件设计原则之里氏代换原则

时间:2024-09-09 14:55:12浏览次数:5  
标签:软件设计 代换 void 长方形 Rectangle 原理篇 double public rectangle

文章目录

概要

里氏代换原则(Liskov Substitution Principle, LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。

理解说明

  1. 任何父类可以出现的地方,子类一定可以出现。通俗来讲,就是,子类可以扩展父类的功能,但是不能改变父类原有的功能;也就是说,除了添加新方法,尽量不要重写父类的方法。
  2. 通过重写父类的一些方法来完成新的功能,这样写起来虽然比较简单,但是会导致,整个继承体系的可复用性会变差,特别是运用多态比较频繁时,程序出错的概率会非常大!

案例 – 正方形不是长方形

Part I – 不符合LSP 正方形(子类)继承长方形(父类)

在这里插入图片描述

首先创建正方形和长方形的类

// 长方形类
public class Rectangle {
    private double length;
    private double width;
    // 相应的getter、setter方法
}

// 正方形类
public class Square extends Rectangle{
	// 重写了父类的方法
    @Override
    public void setLength(double length) {
        super.setLength(length);
        super.setWidth(length);
    }

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

由代码可见,正方形类重写了长方形类的两个set方法,用于将正方形的长宽设置成同一个值,那么我们在调用的时候,就会出现一些问题

	// 首先定义两个方法
	// 如果长方形的长 小于等于 宽,那么给长重新赋值为 长 + 1
    public static void resize(Rectangle rectangle) {
        //判断宽比长小,进行扩宽
        while (rectangle.getLength() <= rectangle.getWidth()) {
            rectangle.setLength(rectangle.getLength() + 1);
        }
    }
	// 打印长方形的长和宽
    public static void printLengthAndWidth(Rectangle rectangle) {
        System.out.println(rectangle.getLength());
        System.out.println(rectangle.getWidth());
    }

	// 然后开始调用
	public static void main(String[] args) {
        Rectangle rectangle = new Rectangle();
        rectangle.setWidth(20);
        rectangle.setLength(10);

        //扩长 
        resize(rectangle);
        printLengthAndWidth(rectangle);

        System.out.println("============================");
        Square s = new Square();
        s.setLength(10);
        resize(s);
        printLengthAndWidth(s);
    }


--------结果输出:
20.0
21.0
============================
此处会卡住,因为正方形的setLength方法会给长宽重新赋值,所以无限循环

Part I – 结论

运行这段代码就会发现,把一个长方形作为参数传入resize方法中,能实现我们的预期;但如果传入的是一个正方向,那么代码会一直运行下去,直至系统产生溢出错误。所以可以得出结论:在resize方法中,Rectangle类型的参数是不能被Square类型的参数所代替,如果进行了替换就得不到预期结果。因此,Square类和Rectangle类之间的继承关系违反了里氏代换原则,它们之间的继承关系不成立,正方形不是长方形。那么我们如何改进呢?

Part II – 符合LSP

我们需要重新设计他们之间的关系。
在这里插入图片描述
抽象出来一个四边形接口(Quadrilateral),让Rectangle类Square类实现Quadrilateral接口

	// 首先抽象出一个四边形接口
	public interface Quadrilateral {
	    //获取长
	    double getLength();
	    //获取宽
	    double getWidth();
	}
-------------------------------------------------------------------------------------
	// 长方形类和正方形类,都实现这个接口
	public class Rectangle implements Quadrilateral{
	    private double length;
	    private double width;
	
	    @Override
	    public double getLength() {
	        return length;
	    }
	
	    public void setLength(double length) {
	        this.length = length;
	    }
	
	    public double getWidth() {
	        return width;
	    }
	
	    public void setWidth(double width) {
	        this.width = width;
	    }
	}

-------------------------------------------------------------------------------------
	
	public class Square implements Quadrilateral {
	
	    //边长
	    private double side;
	
	    public double getSide() {
	        return side;
	    }
	
	    public void setSide(double side) {
	        this.side = side;
	    }
	
	    @Override
	    public double getLength() {
	        return side;
	    }
	
	    @Override
	    public double getWidth() {
	        return side;
	    }
	}

这样,长方形和正方形可以分别实现自己的get方法,那么我们在相同的调用时,就可以只针对长方形进行扩长,参数为长方形类,对打印的方法,参数为四边形接口,这样就可以实现里氏代换原则

	// 如果长方形的长 小于等于 宽,那么给长重新赋值为 长 + 1
    public static void resize(Rectangle rectangle) {
        //判断宽比长小,进行扩宽
        while (rectangle.getLength() <= rectangle.getWidth()) {
            rectangle.setLength(rectangle.getLength() + 1);
        }
    }
	// 打印长方形的长和宽
    public static void printLengthAndWidth(Rectangle rectangle) {
        System.out.println(rectangle.getLength());
        System.out.println(rectangle.getWidth());
    }

	// 开始调用
    public static void main(String[] args) {
        Rectangle r = new Rectangle();
        r.setLength(10);
        r.setWidth(20);
        resize(r);
        printLengthAndWidth(r);
        System.out.println("============================");
        Square s = new Square();
        s.setSide(10);
        printLengthAndWidth(s);
    }



------------------运行结果:
21.0
20.0
============================
10.0
10.0

标签:软件设计,代换,void,长方形,Rectangle,原理篇,double,public,rectangle
From: https://blog.csdn.net/hitman_may_cry/article/details/141932172

相关文章

  • 软件设计之JavaWeb(1)
    软件设计之JavaWeb(1)此篇应在MySQL之后进行学习:路线图推荐:【Java学习路线-极速版】【Java架构师技术图谱】尚硅谷全新JavaWeb教程,企业主流javaweb技术栈资料可以去尚硅谷官网免费领取此章节最好学完JDBC观看学习内容:XML概述TomcatIDEA开发并部署运行WEB项目XML概......
  • 读软件设计的要素03概念的组合
    1. 概念的组合1.1. 概念不像程序那样,可以用较大的包含较小的1.1.1. 每个概念对用户来说都是平等的,软件或系统就是一组串联运行的概念组合1.2. 概念是通过操作来同步组合的1.2.1. 同步并不增加新的概念操作,但会限制已有的操作,从而消除一些独立概念可能会出现的操作序......
  • 面向对象开发重点摘要【软件设计师】
    文章目录前言一、面向对象基础1.1基本概念1.2面向对象开发流程二、UML2.1UML图的概念及分类2.2UML中的关系三、设计模式3.1设计模式分类汇总3.2创建型模式3.3结构型模式3.4行为型模式前言本文是在备考软考-软件设计师时编写的,为了记忆重点内容,内容较为简略,只是粗......
  • 【软考中级攻略站】-软件设计师(1)-数值及其转换和数据表示
    进制转换n进制->十进制步骤说明:识别基数:首先确认你正在处理的是n进制数,这里的n就是该数的基数。数位权重:从右向左数,每个位置上的数字都有一个权重,最右边的位置权重为0,依次向左递增。计算值:将每个位置上的数字乘以基数的相应幂次方,然后将所有的结果相加起来。假设有一......
  • 软考超详细准备之软件设计师的计算机系统题型二(上午题)
    目录流水线存储器:cacheCache命中率的相关图形中断相关习题输入和输出相关习题 总线相关习题加密技术与认证技术相关习题加密技术相关习题杂题流水线流水线(Pipeline)是一种在硬件设计中用于提高效率和吞吐量的技术,尤其在处理器设计中非常常见。流水线将一个......
  • 项目管理重点摘要【软考(软件设计师)】
    文章目录前言一、进度管理1.1进度管理的关键步骤1.2工具和方法1.3甘特图1.4关键路径分析法二、风险管理三、成本管理四、沟通管理前言一、进度管理1.1进度管理的关键步骤制定项目或生产计划:管理者需要根据项目或生产的目标、范围、资源等因素,制定出详细的项目或......
  • 前端速通面经八股系列(八)—— 全网最高质量的前端浏览器原理篇
    浏览器原理系列目录一、浏览器安全1.什么是XSS攻击?(1)概念(2)攻击类型2.如何防御XSS攻击?3.什么是CSRF攻击?(1)概念(2)攻击类型4.如何防御CSRF攻击?5.什么是中间人攻击?如何防范中间人攻击?6.有哪些可能引起前端安全的问题?7.网络劫持有哪几种,如何防范?二、进程与线......
  • 软考软件设计师考前必看-多10分版
         ......
  • 软件设计师全套备考系列文章13 -- 数据库:概念、三级模式两级映像、设计过程、数据模型
    软考--软件设计师(13)--数据库:概念、三级模式两级映像、设计过程、数据模型文章目录软考--软件设计师(13)--数据库:概念、三级模式两级映像、设计过程、数据模型前言一、章节考点二、基本概念三、三级模式、两级映像四、设计过程五、数据模型前言考试时间:每年5月、......
  • 软件设计师全套备考系列文章15 -- 数据库:规范化、控制功能、大数据
    软考--软件设计师(15)--数据库:规范化、控制功能、大数据文章目录软考--软件设计师(15)--数据库:规范化、控制功能、大数据前言一、章节考点二、规范化三、数据库的控制功能四、大数据、数据仓库前言考试时间:每年5月、11月,软件设计师每年都会开考。考试条件:三不限......