设计模式原则——里氏替换原则
设计模式原则
设计模式示例代码库地址:
https://gitee.com/Jasonpupil/designPatterns
里氏替换原则
-
继承必须确保父类所拥有的性质在子类中依然成立
-
与开闭原则不同的是开闭原则可以改变父类原有的功能,里氏替换原则不能修改父类的原有的性质,即使子类扩展了父类的功能,也不能改变父类的原有功能
-
提高兼容性、维护性和扩展性
- 子类和父类的接口保持一致,确保在任何使用父类的地方都可以替换为子类,而不会影响系统功能
- 子类能够无缝地替换父类,替换时不需要修改客户端代码,方便地扩展新功能而不需要对现有代码进行大规模修改
- 由于子类完全遵循父类的契约,系统在替换子类时不容易出现未预见的运行时错误
使用场景:银行卡存储,
- 信用卡继承并重写储蓄卡的功能,破坏了里氏替换原则,根据里氏替换原则进行修改
里氏替换原则替换前示例代码:
储蓄卡类:
/*** @Description: 模拟储蓄卡功能* @Author: pupil* @Date: 2024/06/23 下午 10:04*/
public class CashCard {private Logger logger = LoggerFactory.getLogger(CashCard.class);private static List<String> tradeList = new ArrayList<>();/*** 提现** @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/public String withdrawal(String orderId, BigDecimal amount) {// 模拟支付成功logger.info("提现成功,单号:{} 金额:{}", orderId, amount);return "0000";}/*** 储蓄** @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/public String recharge(String orderId, BigDecimal amount) {// 模拟充值成功logger.info("储蓄成功,单号:{} 金额:{}", orderId, amount);return "0000";}/*** 交易流水查询** @return 交易流水*/public List<String> tradeFlow() {logger.info("交易流水查询成功");tradeList.add("14451,100.00");tradeList.add("14451,65.00");tradeList.add("14451,76.50");tradeList.add("14451,126.00");return tradeList;}
}
信用卡类:
/*** @Description: 模拟信用卡功能,重写父类的方法,违法里氏替换原则* @Author: pupil* @Date: 2024/06/23 下午 10:32*/public class CreditCard extends CashCard{private Logger logger = LoggerFactory.getLogger(CashCard.class);/*** @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/@Overridepublic String withdrawal(String orderId, BigDecimal amount) {// 校验if (amount.compareTo(new BigDecimal(1000)) >= 0){logger.info("贷款金额校验(限额1000元),单号:{} 金额:{}", orderId, amount);return "0001";}// 模拟生成贷款单logger.info("生成贷款单,单号:{} 金额:{}", orderId, amount);// 模拟支付成功logger.info("贷款成功,单号:{} 金额:{}", orderId, amount);return "0000";}/**** @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/@Overridepublic String recharge(String orderId, BigDecimal amount) {// 模拟生成还款单logger.info("生成还款单,单号:{} 金额:{}", orderId, amount);// 模拟还款成功logger.info("还款成功,单号:{} 金额:{}", orderId, amount);return "0000";}@Overridepublic List<String> tradeFlow() {return super.tradeFlow();}}
测试类:
/*** @Description: 验证测试* @Author: pupil* @Date: 2024/06/23 下午 10:33*/public class ApiTest {private Logger logger = LoggerFactory.getLogger(ApiTest.class);@Testpublic void test_CashCard() {CashCard cashCard = new CashCard();// 提现cashCard.withdrawal("14451", new BigDecimal(100));// 储蓄cashCard.recharge("14451", new BigDecimal(100));// 交易流水List<String> tradeFlow = cashCard.tradeFlow();logger.info("查询交易流水,{}", JSON.toJSONString(tradeFlow));}@Testpublic void test_CreditCard() {CreditCard creditCard = new CreditCard();// 支付creditCard.withdrawal("14451", new BigDecimal(100));// 还款creditCard.recharge("14451", new BigDecimal(100));// 交易流水List<String> tradeFlow = creditCard.tradeFlow();logger.info("查询交易流水,{}", JSON.toJSONString(tradeFlow));}}
结果:
里氏替换原则替换后示例代码:
银行卡类:
/**
* @Description: 银行卡
* @Author: pupil
* @Date: 2024/06/23 下午 10:46
*/
public abstract class BankCard {private Logger logger = LoggerFactory.getLogger(BankCard.class);private static List<String> tradeList = new ArrayList<String>();private String cardId; // 卡号private String cardDate; // 开卡时间public BankCard(String cardId, String cardDate) {this.cardId = cardId;this.cardDate = cardDate;}abstract boolean rule(BigDecimal amount);/*** 正向入账,+ 钱* @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/public String positive(String orderId, BigDecimal amount) {// 入款成功,存款、还款logger.info("卡号{} 入款成功,单号:{} 金额:{}", cardId, orderId, amount);return "0000";}/*** 逆向入账,- 钱* @param orderId* @param amount* @return 状态码 0000成功、0001失败、0002重复*/public String negative(String orderId, BigDecimal amount) {// 入款成功,存款、还款logger.info("卡号{} 出款成功,单号:{} 金额:{}", cardId, orderId, amount);return "0000";}/*** 交易流水查询** @return 交易流水*/public List<String> tradeFlow() {logger.info("交易流水查询成功");tradeList.add("14451,100.00");tradeList.add("14451,80.00");tradeList.add("14451,76.50");tradeList.add("14451,126.00");return tradeList;}public String getCardId() {return cardId;}public String getCardDate() {return cardDate;}
}/**
* @Description: 模拟储蓄卡功能
* @Author: pupil
* @Date: 2024/06/23 下午 10:04
*/
public class CashCard extends BankCard {private Logger logger = LoggerFactory.getLogger(CashCard.class);public CashCard(String cardNo, String cardDate) {super(cardNo, cardDate);}boolean rule(BigDecimal amount) {return true;}/*** 提现** @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/public String withdrawal(String orderId, BigDecimal amount) {// 模拟支付成功logger.info("提现成功,单号:{} 金额:{}", orderId, amount);return super.negative(orderId, amount);}/*** 储蓄** @param orderId 单号* @param amount 金额*/public String recharge(String orderId, BigDecimal amount) {// 模拟充值成功logger.info("储蓄成功,单号:{} 金额:{}", orderId, amount);return super.positive(orderId, amount);}}
信用卡类:
/**
* @Description: 模拟信用卡功能,重写父类的方法,违法里氏替换原则
* @Author: pupil
* @Date: 2024/06/23 下午 10:32
*/
public class CreditCard extends CashCard{private Logger logger = LoggerFactory.getLogger(CashCard.class);public CreditCard(String cardNo, String cardDate) {super(cardNo, cardDate);}/*** 金额规则* 根据里氏替换原则不能重写父类的rule方法,所以新构建一个方法* @param amount* @return*/boolean rule2(BigDecimal amount) {return amount.compareTo(new BigDecimal(1000)) <= 0;}/*** 提现,信用卡贷款** @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/public String loan(String orderId, BigDecimal amount) {boolean rule = rule2(amount);if (!rule) {logger.info("生成贷款单失败,金额超限。单号:{} 金额:{}", orderId, amount);return "0001";}// 模拟生成贷款单logger.info("生成贷款单,单号:{} 金额:{}", orderId, amount);// 模拟支付成功logger.info("贷款成功,单号:{} 金额:{}", orderId, amount);return super.negative(orderId, amount);}/*** 还款,信用卡还款** @param orderId 单号* @param amount 金额* @return 状态码 0000成功、0001失败、0002重复*/public String repayment(String orderId, BigDecimal amount) {// 模拟生成还款单logger.info("生成还款单,单号:{} 金额:{}", orderId, amount);// 模拟还款成功logger.info("还款成功,单号:{} 金额:{}", orderId, amount);return super.positive(orderId, amount);}
}
测试类:
/**
* @Description: 测试验证
* @Author: pupil
* @Date: 2024/06/23 下午 10:51
*/
public class ApiTest {private Logger logger = LoggerFactory.getLogger(ApiTest.class);@Testpublic void test_bankCard() {logger.info("里氏替换前,CashCard类:");CashCard bankCard = new CashCard("800999898", "2024-06-23");// 提现bankCard.withdrawal("14451", new BigDecimal(100));// 储蓄bankCard.recharge("14451", new BigDecimal(100));logger.info("里氏替换后,CreditCard类:");CashCard creditCard = new CreditCard("800999898", "2024-06-23");// 提现creditCard.withdrawal("14451", new BigDecimal(1000000));// 储蓄creditCard.recharge("14451", new BigDecimal(100));// 交易流水List<String> tradeFlow = bankCard.tradeFlow();logger.info("查询交易流水,{}", JSON.toJSONString(tradeFlow));}@Testpublic void test_CreditCard(){CreditCard creditCard = new CreditCard("800999898", "2024-06-23");// 支付,贷款creditCard.loan("14451", new BigDecimal(100));// 还款creditCard.repayment("14451", new BigDecimal(100));// 交易流水List<String> tradeFlow = creditCard.tradeFlow();logger.info("查询交易流水,{}", JSON.toJSONString(tradeFlow));}
}
结果:
根据里氏替换原则的示例类图:

银行卡和储蓄卡是泛化关系,储蓄卡继承于银行卡
储蓄卡和信用卡是泛化关系,信用卡继承于储蓄卡
相关文章:
设计模式原则——里氏替换原则
设计模式原则 设计模式示例代码库地址: https://gitee.com/Jasonpupil/designPatterns 里氏替换原则 继承必须确保父类所拥有的性质在子类中依然成立 与开闭原则不同的是开闭原则可以改变父类原有的功能,里氏替换原则不能修改父类的原有的性质&#…...
详解 ClickHouse 的 SQL 操作
传统关系型数据库(以 MySQL 为例)的 SQL 语句,ClickHouse 基本都支持 一、插入 --语法: insert into table_name values(xxxxxx),(yyyyyyy),...;insert into table_name select xxxxx from table_name2 where yyyyy;二、更新和删…...
WPF与Winform,你的选择是?
概述 在桌面应用的发展历程中,Winform和WPF作为微软推出的两大框架,各自承载着不同的设计理念和技术特色。Winform以其稳定、成熟的技术基础,长期占据着企业级应用开发的重要地位。而WPF,作为后来者,以其现代化的UI设计…...
基于SpringBoot的实习管理系统设计与实现
你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。 开发语言: Java 数据库: MySQL 技术: SpringBoot框架,B/S模式 工具: MyEclipse,Tomcat 系统展示 …...
编程用什么电脑不卡的:深度解析与推荐
编程用什么电脑不卡的:深度解析与推荐 在编程的世界里,一台流畅不卡的电脑无疑是每个开发者的得力助手。然而,面对市场上琳琅满目的电脑品牌和型号,如何选择一台适合编程的电脑却成为了一个令人困惑的问题。本文将从四个方面、五…...
优先级队列模拟实现
目录 1.堆的概念 2.堆性质堆中的某个元素小于或大于他的左右孩子 3.小根堆实例 4.堆创建 4.1调整思路 4.2向下调整思路 4.3代码实现(大根堆) 5.堆的删除 6.堆的插入 7.常用接口 7.1PriorityQueue和PriorityBlockingQueue 1.堆的概念 如果有一…...
记一次服务器崩溃事件
今天在安装Jenkins的时候,进行到插件安装这一步,本来一切顺利,结果最后安装完成之后一直进不去网页,显示连接超时,网上搜索了一圈也没发现什么相似的情况,当我疑惑的时候回到Linux控制台,发现命…...
神经网络 #数据挖掘 #Python
神经网络是一种受生物神经元系统启发的人工计算模型,用于模仿人脑的学习和决策过程。它由大量互相连接的节点(称为神经元)组成,这些节点处理和传递信息。神经网络通常包含输入层、隐藏层(可有多个)和输出层…...
营销复盘秘籍,6步法让你的活动效果翻倍
在营销的世界中,每一次活动都是一次探险,而复盘就是探险后的宝藏图,指引我们发现问题、提炼经验、优化策略。 想要学习如何复盘,只要了解以下复盘六大步骤,即可不断总结,逐渐走向卓越。 第一步࿱…...
Linux下命令行文件创建删除、目录创建删除
在Linux命令行下,文件和目录的创建与删除是通过一系列基础命令完成的,这些命令对于日常的系统管理和文件操作至关重要。 下面将详细介绍这些命令的功能和使用方法。 普通文件的创建与删除 创建文件 touch命令:主要用于创建一个空文件&…...
数字排列问题
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 代码: #include <stdio.h> int main() { int count 0; // 计数器,记录生成的三位数的数量 // 使用三个嵌套的fo…...
CentOS Linux 7系统中离线安装MySQL5.7步骤
预计数据文件存储目录为:/opt/mysql/data 1、文件下载: 安装文件下载链接:https://downloads.mysql.com/archives/community/ 2、检查当前系统是否安装过MySQL [rootcnic51 mysql]# rpm -qa|grep mariadb mariadb-libs-5.5.68-1.el7.x86_6…...
XSS跨站攻击漏洞
XSS跨站攻击漏洞 一 概述 1 XSS概述 xss全称为:Cross Site Scripting,指跨站攻击脚本,XSS漏洞发生在前端,攻击的是浏览器的解析引擎,XSS就是让攻击者的JavaScript代码在受害者的浏览器上执行。 XSS攻击者的目的就是…...
PMP到底值不值得考?
首先,咱们得明白PMP是个啥。 PMP,全称Project Management Professional,是美国项目管理协会PMI颁发的一个项目管理专业人士资格认证。 PMP证书在项目管理领域可是有着举足轻重的地位,与MBA、MPA并驾齐驱,被称为“全球…...
redis面试总结
redis的数据类型? string字符串:类似于java中Map<String,String>。存储字符串、JSON数据、验证码等。 Hash字典:类似java中Map<String, Map<Spring,String>>。比较适合存储对象数据。 List列表:类似java中Ma…...
大模型日报2024-06-24
大模型日报 2024-06-24 大模型资讯 大模型产品 AI快速生成专业播客 摘要: MakePodcast.io使用AI语音,只需提供脚本并选择声音,即可在几分钟内生成专业质量的播客。 Sherloq:SQL用户的AI协作仓库 摘要: Sherloq为SQL查询提供一站式管理&#x…...
深入理解计算机系统 CSAPP 练习题7.4
A:0x4004e8(-4)-50x4004df B:0x5...
摘苹果-第13届蓝桥杯省赛Python真题精选
[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第88讲。 摘苹果࿰…...
开源项目推荐-vue2+element+axios 个人财务管理系统
文章目录 financialmanagement项目简介项目特色项目预览卫星的实现方式:首次进入卫星效果的实现方式:卫星跟随鼠标滑动的随机效果实现方式:环境准备项目启动项目部署项目地址 financialmanagement 项目简介 vue2elementaxios 个人财务管理系…...
手机数据如何恢复?11 款最佳安卓手机恢复软件
媒体可能由于各种原因而从您的设备中删除,可能是意外或病毒攻击。 在这些情况下,照片恢复应用程序是唯一的解决方案。理想的照片恢复应用程序取决于各种因素,例如存储设备的损坏程度、删除照片后的持续时间以及应用程序使用的恢复算法的有效性…...
SteamShutdown终极指南:让Steam下载完成后自动关机的完整解决方案
SteamShutdown终极指南:让Steam下载完成后自动关机的完整解决方案 【免费下载链接】SteamShutdown Automatic shutdown after Steam download(s) has finished. 项目地址: https://gitcode.com/gh_mirrors/st/SteamShutdown 还在为Steam大型游戏下载而熬夜等…...
探索TinyEditor:400字节内的微型全能代码编辑器
探索TinyEditor:400字节内的微型全能代码编辑器 【免费下载链接】TinyEditor A functional HTML/CSS/JS editor in less than 400 bytes 项目地址: https://gitcode.com/gh_mirrors/ti/TinyEditor 在前端开发工具领域,TinyEditor以其极致精简的设…...
iOS折叠动画终极指南:用Popping打造惊艳视觉效果
iOS折叠动画终极指南:用Popping打造惊艳视觉效果 【免费下载链接】popping A collection of animation examples for iOS apps. 项目地址: https://gitcode.com/gh_mirrors/po/popping 想要为你的iOS应用添加令人惊艳的折叠动画效果吗?Popping项目…...
STM32实战指南_基于STM32F103的智能交通灯系统设计与实现(硬件+软件+调试)
1. 项目背景与需求分析 十字路口的交通拥堵是城市治理的经典难题。传统定时切换的交通灯就像个固执的老头子,不管车多车少都按固定节奏工作,经常出现一边排长龙、另一边空荡荡的尴尬场景。这次我们要用STM32F103这颗"最强大脑"给交通灯装上&qu…...
Focaler-IoU: More Focused Intersection over Union——更聚焦的交并比损失
《Focaler-IoU: More Focused Intersection over Union Loss》主要研究内容可以全面概括如下: 研究背景与问题: 在目标检测任务中,边界框回归的精度很大程度上取决于损失函数的设计。现有的IoU-based损失函数(如GIoU、CIoU、EIoU…...
告别PDF转换烦恼:Marker让学术文档秒变Markdown的完整指南
告别PDF转换烦恼:Marker让学术文档秒变Markdown的完整指南 【免费下载链接】marker 一个高效、准确的工具,能够将 PDF 和图像快速转换为 Markdown、JSON 和 HTML 格式,支持多语言和复杂布局处理,可选集成 LLM 提升精度,…...
Anything to RealCharacters 2.5D转真人引擎效果可视化:预处理前后对比与输出质量评估
Anything to RealCharacters 2.5D转真人引擎效果可视化:预处理前后对比与输出质量评估 你是否曾想过,将心爱的动漫角色、游戏立绘或者卡通头像,一键变成一张以假乱真的真人照片?这听起来像是魔法,但现在,借…...
【雷达信号优化】第八章 阵列校准与误差补偿
目录 第八章 阵列校准与误差补偿 8.1 阵列误差模型 8.1.1 幅相误差 8.1.1.1 互耦效应建模 8.1.1.1.1 互耦矩阵的逆矩阵简化 8.2 阵列自校准算法 8.2.1 信号子空间拟合算法 8.2.1.1 交替优化策略 8.2.1.1.1 信源方向与误差参数的迭代更新 8.2.2 辅助源校准 8.2.2.1 单…...
AI印象派艺术工坊WebUI定制:前端界面修改实战案例
AI印象派艺术工坊WebUI定制:前端界面修改实战案例 1. 引言 你有没有想过,自己也能像艺术家一样,把随手拍的照片变成一幅幅精美的画作?素描、彩铅、油画、水彩,这些听起来需要多年绘画功底才能完成的作品,…...
Cadence Virtuoso仿真避坑指南:从网表生成到FFT分析的20个常见错误解决方案
Cadence Virtuoso仿真避坑指南:从网表生成到FFT分析的20个常见错误解决方案 在集成电路设计领域,Cadence Virtuoso作为行业标准工具链的核心组件,其仿真功能的正确使用直接关系到设计效率与结果可靠性。本文将系统梳理从网表生成到FFT分析全流…...




