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

设计模式原则——里氏替换原则

设计模式原则

设计模式示例代码库地址:

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));}
}
结果:
  • 在这里插入图片描述

  • 在这里插入图片描述

根据里氏替换原则的示例类图:

在这里插入图片描述

银行卡和储蓄卡是泛化关系,储蓄卡继承于银行卡

储蓄卡和信用卡是泛化关系,信用卡继承于储蓄卡

相关文章:

设计模式原则——里氏替换原则

设计模式原则 设计模式示例代码库地址&#xff1a; https://gitee.com/Jasonpupil/designPatterns 里氏替换原则 继承必须确保父类所拥有的性质在子类中依然成立 与开闭原则不同的是开闭原则可以改变父类原有的功能&#xff0c;里氏替换原则不能修改父类的原有的性质&#…...

详解 ClickHouse 的 SQL 操作

传统关系型数据库&#xff08;以 MySQL 为例&#xff09;的 SQL 语句&#xff0c;ClickHouse 基本都支持 一、插入 --语法&#xff1a; insert into table_name values(xxxxxx),(yyyyyyy),...;insert into table_name select xxxxx from table_name2 where yyyyy;二、更新和删…...

WPF与Winform,你的选择是?

概述 在桌面应用的发展历程中&#xff0c;Winform和WPF作为微软推出的两大框架&#xff0c;各自承载着不同的设计理念和技术特色。Winform以其稳定、成熟的技术基础&#xff0c;长期占据着企业级应用开发的重要地位。而WPF&#xff0c;作为后来者&#xff0c;以其现代化的UI设计…...

基于SpringBoot的实习管理系统设计与实现

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; SpringBoot框架&#xff0c;B/S模式 工具&#xff1a; MyEclipse&#xff0c;Tomcat 系统展示 …...

编程用什么电脑不卡的:深度解析与推荐

编程用什么电脑不卡的&#xff1a;深度解析与推荐 在编程的世界里&#xff0c;一台流畅不卡的电脑无疑是每个开发者的得力助手。然而&#xff0c;面对市场上琳琅满目的电脑品牌和型号&#xff0c;如何选择一台适合编程的电脑却成为了一个令人困惑的问题。本文将从四个方面、五…...

优先级队列模拟实现

目录 1.堆的概念 2.堆性质堆中的某个元素小于或大于他的左右孩子 3.小根堆实例 4.堆创建 4.1调整思路 4.2向下调整思路 4.3代码实现&#xff08;大根堆&#xff09; 5.堆的删除 6.堆的插入 7.常用接口 7.1PriorityQueue和PriorityBlockingQueue 1.堆的概念 如果有一…...

记一次服务器崩溃事件

今天在安装Jenkins的时候&#xff0c;进行到插件安装这一步&#xff0c;本来一切顺利&#xff0c;结果最后安装完成之后一直进不去网页&#xff0c;显示连接超时&#xff0c;网上搜索了一圈也没发现什么相似的情况&#xff0c;当我疑惑的时候回到Linux控制台&#xff0c;发现命…...

神经网络 #数据挖掘 #Python

神经网络是一种受生物神经元系统启发的人工计算模型&#xff0c;用于模仿人脑的学习和决策过程。它由大量互相连接的节点&#xff08;称为神经元&#xff09;组成&#xff0c;这些节点处理和传递信息。神经网络通常包含输入层、隐藏层&#xff08;可有多个&#xff09;和输出层…...

营销复盘秘籍,6步法让你的活动效果翻倍

在营销的世界中&#xff0c;每一次活动都是一次探险&#xff0c;而复盘就是探险后的宝藏图&#xff0c;指引我们发现问题、提炼经验、优化策略。 想要学习如何复盘&#xff0c;只要了解以下复盘六大步骤&#xff0c;即可不断总结&#xff0c;逐渐走向卓越。 第一步&#xff1…...

Linux下命令行文件创建删除、目录创建删除

在Linux命令行下&#xff0c;文件和目录的创建与删除是通过一系列基础命令完成的&#xff0c;这些命令对于日常的系统管理和文件操作至关重要。 下面将详细介绍这些命令的功能和使用方法。 普通文件的创建与删除 创建文件 touch命令&#xff1a;主要用于创建一个空文件&…...

数字排列问题

题目&#xff1a;有1、2、3、4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f; 代码&#xff1a; #include <stdio.h> int main() { int count 0; // 计数器&#xff0c;记录生成的三位数的数量 // 使用三个嵌套的fo…...

CentOS Linux 7系统中离线安装MySQL5.7步骤

预计数据文件存储目录为&#xff1a;/opt/mysql/data 1、文件下载&#xff1a; 安装文件下载链接&#xff1a;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全称为&#xff1a;Cross Site Scripting&#xff0c;指跨站攻击脚本&#xff0c;XSS漏洞发生在前端&#xff0c;攻击的是浏览器的解析引擎&#xff0c;XSS就是让攻击者的JavaScript代码在受害者的浏览器上执行。 XSS攻击者的目的就是…...

PMP到底值不值得考?

首先&#xff0c;咱们得明白PMP是个啥。 PMP&#xff0c;全称Project Management Professional&#xff0c;是美国项目管理协会PMI颁发的一个项目管理专业人士资格认证。 PMP证书在项目管理领域可是有着举足轻重的地位&#xff0c;与MBA、MPA并驾齐驱&#xff0c;被称为“全球…...

redis面试总结

redis的数据类型&#xff1f; string字符串&#xff1a;类似于java中Map<String,String>。存储字符串、JSON数据、验证码等。 Hash字典&#xff1a;类似java中Map<String, Map<Spring,String>>。比较适合存储对象数据。 List列表&#xff1a;类似java中Ma…...

大模型日报2024-06-24

大模型日报 2024-06-24 大模型资讯 大模型产品 AI快速生成专业播客 摘要: MakePodcast.io使用AI语音&#xff0c;只需提供脚本并选择声音&#xff0c;即可在几分钟内生成专业质量的播客。 Sherloq&#xff1a;SQL用户的AI协作仓库 摘要: Sherloq为SQL查询提供一站式管理&#x…...

深入理解计算机系统 CSAPP 练习题7.4

A:0x4004e8(-4)-50x4004df B:0x5...

摘苹果-第13届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第88讲。 摘苹果&#xff0…...

开源项目推荐-vue2+element+axios 个人财务管理系统

文章目录 financialmanagement项目简介项目特色项目预览卫星的实现方式&#xff1a;首次进入卫星效果的实现方式&#xff1a;卫星跟随鼠标滑动的随机效果实现方式&#xff1a;环境准备项目启动项目部署项目地址 financialmanagement 项目简介 vue2elementaxios 个人财务管理系…...

手机数据如何恢复?11 款最佳安卓手机恢复软件

媒体可能由于各种原因而从您的设备中删除&#xff0c;可能是意外或病毒攻击。 在这些情况下&#xff0c;照片恢复应用程序是唯一的解决方案。理想的照片恢复应用程序取决于各种因素&#xff0c;例如存储设备的损坏程度、删除照片后的持续时间以及应用程序使用的恢复算法的有效性…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...