LSP:里氏替换原则

系列文章目录

C++高性能优化编程系列
深入理解设计原则系列
深入理解设计模式系列
高级C++并发线程编程

LSP:里氏替换原则

  • 系列文章目录
  • 1、里氏替换原则的定义和解读
  • 2、里氏替换原则可以用于哪些设计模式中?
  • 3、如何使用里氏替换原则来降低代码耦合度?
  • 4、违反里氏替换原则的反模式
  • 5、案例解读
  • 6、里氏替换原则与多态的区别
  • 7、小结

1、里氏替换原则的定义和解读

里氏替换原则(Liskov Substitution Principle, LSP)于1986年有Barbara Liskov提出,他当时是这样描述这条原则的:如果S是T的子类型,那么T的对象可以被S的对象所替换,并不影响代码的运行。1996年,Robert Martin在他的SOLID原则中重新描述了里氏替换原则:使用父类对象的函数可以在不了解子类的情况下替换为使用子类对象
结合上面的描述,我们将里氏替换原则描述为:子类对象能够替换到程序中的父类对象出现的任何地方,并且保证程序原有的逻辑行为不变和正确性不被破坏

2、里氏替换原则可以用于哪些设计模式中?

将里氏替换原则应用于设计模式中,它可以用在许多设计模式中,例如:

  1. 工厂模式:子类可以替换父类,而不会影响到工厂的实现。
  2. 策略模式:不同的策略可以被替换,而不会影响到程序的正确性。
  3. 装饰器模式:装饰器可以替换被装饰的对象,而不会破坏程序的可扩展性。
  4. 模板方法模式:子类可以被使用来扩展或修改模板方法,而不会影响到程序的正确性。

总之,里氏替换原则是一个通用的设计原则,可以在许多设计模式中使用,以增强程序的可读性、可维护性和可扩展性。

3、如何使用里氏替换原则来降低代码耦合度?

通过遵循里氏替换原则,可以使得代码更加灵活、可扩展、易维护。下面是几种具体的方法来降低代码耦合度:

  1. 使用接口而不是具体的类:对于一个类,尽可能使用其接口而非具体的实现。这样可以减少对具体实现的依赖,并且可以更容易地替换实现。
  2. 将通用的行为移到基类:将一些通用的方法或属性移动到基类中,这样子类就可以继承这些方法并添加自己的实现,而不是每个子类都去重复实现相同的方法。
  3. 使用抽象类或接口来表示通用行为:通过使用抽象类或接口来表示通用行为,可以使得代码更加灵活和可扩展。当需要添加新的特定行为时,只需要实现新的抽象类或接口即可,而不需要修改已有的代码。
  4. 避免破坏子类的先决条件:子类必须满足其父类的先决条件。如果子类修改了父类的行为,那么子类就不能替代其父类,这会导致代码的耦合度增加。

4、违反里氏替换原则的反模式

在设计子类时,要遵守父类的行为约定(或者为协议)
以下是违反里氏替换原则的例子:

  1. 子类违反父类声明要实现的功能
  2. 子类违反父类对输入、输出和异常约定
  3. 子类违反父类注释中罗列的任何特殊说明

5、案例解读

假设我们有一个License类,其结构如图1所示。该类中有一个名为calcFee的方法,该方法将由 Billing应用程序来调用。而License类有两个子类型:PersonalLicense与BusinnessLicense,这两个类会用不同的算法来计算授权费用。
在这里插入图片描述

图1:License类与其衍生类,体现了LSP原则

上述设计符合LSP原则,因为Billing应用程序的行为并不依赖于其使用的任何一个衍生类。也就是说,这两个衍生类的对象都是可以用来替换License类对象的。

正方形/长方形问题是一个著名的违反LSP设计原则的案例,该问题结构如图2所示。
在这里插入图片描述

图2:正方形/长方形问题,违反了LSP原则
在这个案例中,Square类并不是Rectangle类的子类型,因为Rectangle类的高和宽可以分别修改,而Square类的高和宽则必须一同修改。由于User类始终认为自己在操作Rectangle类,因此会带来一些混淆。例如在下面的代码中:
Rectangle r = ...
r.setW(5);
r.setH(2);
assert(r.area() == 10);

很显然,如果上述代码在…处返回的是Square类,则最后assert是不会成立的。

6、里氏替换原则与多态的区别

多态是一种代码实现思路,而里氏替换原则是一种设计原则,用来指导继承关系中子类的设计:在替换父类时,确保不改变程序原有的逻辑行为,以及不破坏程序的正确性。

7、小结

里氏替换原则存在的意义:

  • 提高代码的可维护性。遵循里氏替换原则可以使代码的结构更加清晰,如果程序中的对象可以互相替换,那么维护代码的时候就能够更方便地进行修改和扩展。
  • 提高代码的可扩展性。遵循里氏替换原则,可以使代码更容易扩展。如果代码中的对象可以互相替换,那么新的子类可以很容易地替换已有的类,从而实现代码的扩展,而不需要修改原有的代码。
  • 增加代码的可读性。如果遵循里氏替换原则,代码中的类之间的关系会更加清晰明了,这对于其他开发人员来说也更容易理解和阅读。
  • 提高代码的健壮性。遵循里氏替换原则可以使程序更加健壮。如果程序中的对象可以互相替换,那么程序的稳定性和可靠性也会得到提高。
  • 促进代码重用。遵循里氏替换原则,可以使代码更容易重用。如果程序中的对象可以互相替换,那么可以将已有的对象用于新的场景中,从而避免了重复编写代码的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/24226.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT原理简介

承接上文GPT前2代版本简介 GPT3的基本思想 GPT2没有引起多大轰动,真正改变NLP格局的是第三代版本。 GPT3训练的数据包罗万象,上通天文下知地理,所以它会胡说八道,会说的贼离谱,比如让你穿越到唐代跟李白对诗,不在一…

windows里怎么杀死一个进程?

我们可以使用 taskkill 命令,可以使用该工具按照进程 ID (PID) 或映像名称终止任务。 显示帮助消息: taskkill /?参数列表: /S:system:指定要连接的远程系统。/U:[domain\]user:指定应该在哪…

第五篇:强化学习基础之马尔科夫决策过程

你好,我是zhenguo(郭震) 今天总结强化学习第五篇:马尔科夫决策过程 基础 马尔科夫决策过程(MDP)是强化学习的基础之一。下面统一称为:MDP MDP提供了描述序贯决策问题的数学框架。 它将决策问题建模为: 状态…

7种PCB走线方式

01电源布局布线相关 数字电路很多时候需要的电流是不连续的,所以对一些高速器件就会产生浪涌电流。 如果电源走线很长,则由于浪涌电流的存在进而会导致高频噪声,而此高频噪声会引入到其他信号中去。 而在高速电路中必然会存在寄生电感和寄…

STM32G4 比较器COMPx(寄存器开发)

目录 1. 特性1.1 框图1.2 比较器输入信号SEL1.3 比较器滞回选择HYST1.4 比较器的输出1.5 LOCK机制 2. 编程2.1 初始化步骤2.2 举例 STM内部的比较器是模拟量的比较器,其与APB2时钟同步,在RCC时钟控制器中没有COMx时钟使能标志位,其时钟的使能…

RTOS专栏(一) —— rt-thread简单介绍和qemu使用

本期主题: 简单介绍rt-thread介绍qemu和rt-thread怎么配合使用qemu的简单例子 rt-thread & qemu 1.rt-thread介绍2.qemu介绍3.搭建rt-thread和qemu开发环境4.简单例子 1.rt-thread介绍 RT-Thread 是一款完全由国内团队开发维护的嵌入式实时操作系统&#xff0…

JAVA POI excel 添加下拉字典的方式与案例 以及图文详解及个人理解

场景 原有的Excel 某一个 sheet 页中某些列需要添加指定的字典下拉,而这些字典的值又是确认的。 有两种思路: 一、如果给定的下拉字典值是确定的而且关联原有列的位置也不会变,那么这些数据可以固定写死在代码中,也是最简单的一…

北邮22信通:利用BF算法解决实际问题:题目实战(超详解)设计函数 char *locatesubstr(char *str1,char *str2)

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 获取更多文章 请访问专栏~ 北邮22信通_青山如墨雨如画的博客-CSDN博客 目录 题干描述 解析 1.string库函数 2.使用KMP算法思想 注解1 注解2 注解3 题…

学懂缓存雪崩,缓存击穿,缓存穿透仅需一篇,基于Redis讲解

在了解缓存雪崩、击穿、穿透这三个问题前,我们需要知道为什么我们需要缓存。在了解这三个问题后,我们也必须知道使用Redis时,如何解决这些问题。 所以我将按照"为什么我们需要缓存"、"什么是缓存雪崩、击穿、穿透"、&qu…

​字创未来 方正字库第十二届“方正奖”设计大赛正式来袭

传承汉字文化精髓,方正字库在字体行业不断探索深耕。方正字库一直致力于弘扬中华汉字文化,不断促进行业字体设计创新发展。于2001年在行业最艰难的时候,怀揣着对字体设计未来的美好向往,首届“北大方正奖”印刷字体设计大赛&#…

家政服务预约APP的系统设计与实现

摘 要:针对家政行业蓬勃发展,老套的家政服务方式已经跟不上互联网时代的步伐这个问题。基于Android移动平台的分析和设计过程、C/S模式、Eclipse平台,采用Java语言进行开发设计,设计了基于MVC架构的实现方案。安卓客户端与服务器…

Flume系列:Flume通道拓扑结构

目录 Apache Hadoop生态-目录汇总-持续更新 1: 基础架构 2:简单串联 3:复制(Replicating)和多路复用(Multiplexing) 4:负载均衡和故障转移 5:聚合 Apache Hadoop生态-目录汇总-持续更新 系统环境:centos7 Java环境…

IDEA 创建 Springmvc 项目

一、概述 在18年的时候就开始接触 SpringBoot ,然后就一直在使用它。众所周知 SpringBoot 内嵌 Tomcat,后续再也没有单独新建过Web 项目。作为IDEA 的用户,总想要用它来建一个Web 项目自己跑一跑,但建项目不是我最终目的~~ &…

好用的自动化框架-Allure

概述 报告主要包含总览、类别、测试套件、图表、时间刻度、功能、包等7大部分,支持自定义诸多信息,包括附件添加、缺陷链接、案例链接、测试步骤、Epic、Feature、Story、Title、案例级别等,相当强大。 allure与pytest的结合使用可以呈现完…

ProtoBuf 语法(一)

系列文章 ProtoBuf 语法(二) ProtoBuf 语法(三) 文章目录 前言一、字段规则二、消息类型的定义与使用2.1 定义2.2 使用 三、enum 类型3.1 定义规则3.2 注意事项 四、any 类型4.1 类型说明4.2 类型使用 五、oneof 类型六、map 类型…

【Vue】二:Vue核心处理---计算属性 监视属性

文章目录 1.计算属性示例2. 监听属性3.补充 1.计算属性示例 实际上计算属性与methods中定义方法基本上没有什么区别,只是计算属性基于响应式依赖缓存,只要数据没有发生改变,计算属性从缓存中取值,只有当数据发送改变,才…

安卓中集成高德地图

安卓中集成高德地图 1.高德地图的优缺点 高德开放平台 | 高德地图API 高德地图优点: 1、领先的地图渲染技术:性能提升10倍,所占空间降低80%,比传统地图软件节省流量超过90% 2、专业在线导航功能&#x…

idea模板配置

idea版本:2023.1 未设置模板的idea,新建类会自动生成类注释 格式如下: /*** author user* date 2023/5/20 0020 14:25*/ public class User {} 其中,user为当前用户名 这里,如果希望将类注释改写成如下&#xff0…

档案馆空气质量在线3D监控系统温湿度方案

档案馆库房八防温湿度空气质量一体化解决方案 档案库房是档案事业发展的基石,其主要任务是集中保管国家机构及个人等在各种形式下形成的具有一定价值和保存价值的各种载体档案,主要包括文书档案、科技档案、会计档案、人事档案、实物档案等。随着我国经济…

X2000 freeRTOS usb_bulk通信

例程 官方例程..\freertos\example\usb\device\gadget_generic_bulk.c&#xff0c;代码如下&#xff1a; #include <common.h> #include <usb/gadget_bulk.h> #include <os.h>static const struct gadget_id bulk_id {.vendor_id 0x1CBE,.product_id 0x…