03 里氏替换原则

官方定义:

里氏替换原则(Liskov Substitution Principle,LSP)是由麻省理工学院计算机科学系教授芭芭拉·利斯科夫于 1987 年在“面向对象技术的高峰会议”(OOPSLA)上发表的一篇论文《数据抽象和层次》(Data Abstractionand Hierarchy)里提出的.
她在论文中提到:如果S是T的子类型,对于S类型的任意对象,如果将他们看作是T类型的对象,则对象的行为也理应与期望的行为一致

子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。

如何理解里氏替换原则?

要理解里氏替换原则,其实就是要理解两个问题:
什么是替换?
什么是与期望行为一致的替换(Robert Martin所说的“必须能够替换”)?

1 ) 什么是替换 ?
替换的前提是面向对象语言所支持的多态特性,同一个行为具有多个不同表现形式或形态的能力。
在这里插入图片描述
2 ) 什么是与期望行为一致的替换?
在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类的实现,都与接口或基类方法的期望行为一致。

不需要关心是哪个类对接口进行了实现,因为不管底层如何实现,最终的结果都会符合接口中关于方法的描述(也就是与接口中方法的期望行为一致).
或者说接口或基类的方法是一种契约,使用方按照这个契约来使用,派生类也按照这个契约来实现。这就是与期望行为一致的替换。

场景案例

比如在一个商城项目中,有3种促销活动:
1)PromotionalStrategy (满减活动,两百以上百八折)
2)RebateStrategy(打折活动)
3)ReduceStrategy(返现活动)
在这里插入图片描述

public interface Istrategy {public double realPrice(double consumePrice);
}
public class PromotionalStrategy implements Istrategy {public double realPrice(double consumePrice) {
if (consumePrice > 200) {
return 200 + (consumePrice - 200) * 0.8;
} else {
return consumePrice;
}
}
}
public class RebateStrategy implements Istrategy {
private final double rate;
public RebateStrategy() {
this.rate = 0.8;
}
public double realPrice(double consumePrice) {
return consumePrice * this.rate;
}
}
public class ReduceStrategy implements Istrategy {
public double realPrice(double consumePrice) {
if (consumePrice >= 1000) {
return consumePrice - 200;
} else {
return consumePrice;
}
}
}

调用方为Context,在此类中使用接口定义了一个对象

public class Context {
//使用基类定义对象变量
private Istrategy strategy;
// 注入当前活动使用的具体对象
public void setStrategy(Istrategy strategy) {
this.strategy = strategy;
}
// 计算并返回费用
public double cul(double consumePrice) {
// 使用具体商品促销策略获得实际消费金额
double realPrice =
this.strategy.realPrice(consumePrice);
// 格式化保留小数点后1位,即:精确到角
BigDecimal bd = new BigDecimal(realPrice);
bd = bd.setScale(1, BigDecimal.ROUND_DOWN);
return bd.doubleValue();
}
}

Context 中代码使用接口定义对象变量,这个对象变量可以是实现了lStrategy
接口的PromotionalStrategy、RebateStrategy 、 ReduceStrategy任意一个。

里氏代换原则与多态的区别 ?

虽然从定义描述和代码实现上 来看,多态和里式替换有点类似,但它们关
注的角度是不一样的。多态是面向对象编程的一 大特性,也是面向对象编
程语言的一种语法。它是一种代码实现的思路。而里式替换是一种 设计原
则,用来指导继承关系中子类该如何设计,子类的设计要保证在替换父类
的时候,不 改变原有程序的逻辑及不破坏原有程序的正确性。

里氏替换原则和依赖倒置原则,构成了面向接口编程的基础,正因为里氏替换
原则,才使得程序呈现多样性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序自定义方法submitPwd(e){}传入的e有什么作用

在微信小程序中,自定义方法(也称为事件处理函数)的参数 e 表示事件对象,用于传递事件的相关信息,包括事件类型、事件目标、事件数据等。通过 e 参数,可以获取事件的详细信息,并对事件进行相应的…

『Linux升级路』基本指令

🔥博客主页:小王又困了 📚系列专栏:Linux 🌟人之为学,不日近则日退 ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、认识操作系统 📒1.1什么是操作系统 📒1.2操作系统…

【RDMA】librdmacm库和连接建立过程

翻译:rdma_cm - RDMA通信管理器。 概述:rdma_cm是用于建立RDMA传输上的通信的管理器。 说明:RDMA CM是一个用于建立可靠连接和不可靠数据报数据传输的通信管理器。它为建立连接提供了一个RDMA传输中立的接口。该API基于套接字,但…

如何处理前端路由懒加载?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

使用dd命令来构造测试文件

近期因工作需要,需要构造大小随机的一些文件,作为测试场景的输入。 在Linux平台下,使用dd命令,可以方便的构造出符合要求的文件。 比如生成4M的文件,同时使用随机数作为输入,命令样例如下: dd…

Pytorch,矩阵求和维度变化解析

二维可以想象成一张纸, 三维可以想象成多张纸叠在一块 四维可以想成多沓纸 求和时,如果没设定keepdimTrue,则会消去相加的那一维度,否则则将维度变为1 A torch.arange(20).reshape(5, 4) A,A.shape, A.sum()(tensor([[ 0, 1, 2, 3],[ 4,…

AWS SAP-C02教程5--基础中间件

在AWS中除了计算、存储、网络之外,还有一些组件非常重要,包括基础组件、消息队列组件、日志组件、编排组件等,接下来就通过分成几个不同类别(这个分类按照AWS的大概分类进行分类,并无统一标准,只是具备一定相同功能归类在一起方便记忆) 目录 1 消息中间件1.1 SQS1.1.1 …

XSS攻击(1), 测试XSS漏洞, 获取cookie

XSS漏洞, 测试XSS漏洞, 获取cookie 一, 概念: XSS(Cross-Site Scripting), 跨站攻击脚本, XSS漏洞发生在前端, 依赖于浏览器的解析引擎, 让前端执行攻击代码. XSS其实也算注入类的攻击, XSS代码注入需要有JavaScript编程基础. 二, 目的: XSS(跨站脚本&#xff0…

js实现红包雨功能(canvas,react,ts),包括图片不规则旋转、大小、转速、掉落速度控制、屏幕最大红包数量控制等功能

介绍 本文功能由canvas实现红包雨功能(index.tsx)本文为react的ts版。如有其他版本需求可评论区观赏地址,需过墙 import React, { Component } from react; // import ./index.css; import moneyx from /assets/images/RedEnvelopeRain/bal…

Ubuntu - 安装 MySQL 8

以下是在 Ubuntu 上安装 MySQL 8 的完整步骤: 步骤 1:更新包列表 首先,打开终端并执行以下命令来确保包列表是最新的: sudo apt update 步骤 2:安装 MySQL 8 服务器 接下来,使用以下命令安装 MySQL 8 …

算水质TDS加温度补偿

先上图,就图里这款水质检测,用树莓派3/4的话,要配个温度检测作为温度校正,以及一个adc 元器件。我选ds18b20和ads1115。 再把模拟数据计算过程放一下: 温度检测元器件在农历钟那里提过,就是同款。此处先测个…

Android11 移植memtester压测内存

需求如题,从网上下载了memtest源码压缩包,准备放到系统源码编译,然后push到板子上执行,结果,编译出来一堆问题,报build err。 做如下代码改动: external/memtester-4.5.1/Android.mk | 16 exte…

Android 10.0 展讯平台关于ota升级开机logo的相关功能实现

1.前言 在android10.0的展讯平台的系统定制开发中,关于ota升级功能的需求也好多,但是对于ota升级开机logo这样的bmp图片,就不能像 升级其他功能一样简单做ota差分包,然后ota升级就可以了,接下来就带大家来实现这个功能 2.展讯平台关于ota升级开机logo的相关功能实现的相…

Java 中的自动装箱和拆箱

Java 中的自动装箱(Autoboxing)和拆箱(Unboxing)是指在基本数据类型和对应的包装类型之间进行自动转换的特性。 自动装箱是指将基本数据类型转换为对应的包装类型。当使用包装类型作为参数传递给需要相应基本数据类型的方法&…

机器学习基础之《回归与聚类算法(4)—逻辑回归与二分类(分类算法)》

一、什么是逻辑回归 1、逻辑回归(Logistic Regression)是机器学习中的一种分类模型,逻辑回归是一种分类算法,虽然名字中带有回归,但是它与回归之间有一定的联系。由于算法的简单和高效,在实际中应用非常广…

tomcat---动静分离

访问静态和动态页面分开 实现动态的静态页面负载均衡 实验一 准备阶段:三台虚拟机 nginx代理服务器 :20.0.0.40 tomcat1 :20.0.0.50 tomcat2:20.0.0.51 配置关闭虚拟机防火墙和安全机制 systemctl stop firewalld setenf…

vue3学习(九)--- keep-alive缓存组件

有时候我们不希望组件被重新渲染影响使用体验;或者处于性能考虑,避免多次重复渲染降低性能。而是希望组件可以缓存下来,维持当前的状态。这时候就需要用到keep-alive组件。 keep-alive有两个独有的生命周期:activated、 deactivated 接下来看…

使用cpolar内网端口映射技术实现U8用友ERP本地部署的异地访问

文章目录 前言1. 服务器本机安装U8并调试设置2. 用友U8借助cpolar实现企业远程办公2.1 在被控端电脑上,点击开始菜单栏,打开设置——系统2.2 找到远程桌面2.3 启用远程桌面 3. 安装cpolar内网穿透3.1 注册cpolar账号3.2 下载cpolar客户端 4. 获取远程桌面…

Linux - 常用基础指令

目录 part 1 ls tree stat part 2 clear pwd echo cd cal date part 3 touch mkdir rmdir rm cp mv part 4 cat more less head tail part 5 find which locate grep part 6 chmod chown chgrp sudo su part 7 uname id man手册 --help…

NTFS磁盘格式读写工具Tuxera NTFS 2023 for Mac中文破解版v2023含最新激活序列号

Tuxera NTFS 2023 Mac 是一个NTFS文件系统驱动程序,为解决Mac上不能对NTFS格式硬盘进行访问和读写而生。实现苹果Mac OS X系统读写Microsoft Windows NTFS文件系统,在硬盘、U盘等外接设备中进行全面访问、删除、修改等相关操作。 tuxera ntfs 2023 破解…