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

设计模式原则

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

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));}
}

结果:

  • 在这里插入图片描述

  • 在这里插入图片描述

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

在这里插入图片描述

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

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

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

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

相关文章

在线装修管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;装修队管理&#xff0c;用户管理&#xff0c;装修管理&#xff0c;基础数据管理&#xff0c;论坛管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;…

197.回溯算法:复原IP地址(力扣)

代码解决 class Solution { public:// 存储最终结果的向量vector<string> result;// 判断字符串s从start到end范围内的子串是否是一个合法的IP地址段bool isValid(const string& s, int start, int end){if (start > end) {return false; // 起始位置大于结束位置…

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档&#xff1a;https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址&#xff1a;https://github.com/Hufe921/canvas-editor 前提声明&#xff1a; 由于CanvasEditor目前不支持vue、react 等框架开箱即用版&#xff0c;所以…

开源seata的分布式事务解决方案-XA、AT、TCC、SAGA哪个模式好

分布式事务是分布式系统中非常重要的一部分。假设一个用户购买商品的业务逻辑&#xff0c;系统有3个微服务组成&#xff0c;分别是订单服务、账户服务、库存服务&#xff0c;用户在提交订单后会从用户账户余额中扣款&#xff0c;同时扣减库存数量。在这样的场景下扣款和减库存需…

IDEA中 pom.xml 设置自动提示

IDEA中 pom.xml 自动提示 IDEA中 pom.xml 自动提示设置如下&#xff1a; file–>Settings–>Build,Execution…–>Build Tools–>Maven–>Repositories 会看到类似表格的画面&#xff0c;内容是你的maven地址&#xff0c;选中后&#xff0c;右边有个Update的按…

开放式耳机哪种好用又实用?开放式耳机必入品牌推荐,内行人分享

随着数码技术的不断推出各种各样的新产品&#xff0c;开放式耳机已经逐渐成为有份音乐发烧友的选择&#xff0c;这类耳机从早期的简单音质发展至今日的高解析度&#xff0c;其技术进步&#xff0c;也吸引了一大批开放式耳机的爱好者&#xff0c;开放式耳机以其开放式的设计&…

2024中国第三方算力中心服务商发展研究报告

来源&#xff1a;科智咨询 近期历史回顾&#xff1a;《江苏省绿色建筑评价标识实施细则》(1).pdf 《江苏省绿色建筑评价标识实施细则》.pdf 【计算工具】钢铁企业碳排放各工序数据收集表.xlsx 【深度报告】钢铁产品碳足迹核算及报告指南.pdf 【专家PPT】宝钢低碳钢铁技术策划及…

巧用newSingleThreadExecutor让异步任务顺序跑

背景 Flume 是 Cloudera 提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传输的系统 。一个用来控制 Flume 采集任务的 Web 应用&#xff0c;需要对任务进行管理&#xff0c;主要操作「启动、停止、新建、编辑、删除」&#xff0c;本质就是对…

头歌——机器、深度学习——手写体识别

第1关&#xff1a;神经网络基本概念 任务描述 本关任务&#xff1a;根据本节课所学知识完成本关所设置的选择题。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.神经网络基本概念。 神经网络基本概念 神经网络由输入层、隐藏层、输出层组成&#xff1b;…

【源码】含70演示高转化率Magento2外贸时装女装跨境电商模板V1.2.2

MagMog是下一代最高转化率和可扩展的跨境电商Magento2主题&#xff0c;让您几乎可以立即上手。这是一个终极解决方案&#xff1a;主题附带一系列电子商务功能&#xff0c;可以启用您商店的隐藏功能&#xff0c;并且您无需支付任何额外费用。 100% 免费。 MagMog从定制设计到内…

AI大模型企业应用实战(16)-langchain核心组件

1 stuff 将文档列表插入到提示词中&#xff0c;适合文档较小或少量文档的应用。 2 refine 通过循环输入文档并迭代更新答案来构建响应&#xff0c;一次只传递给LLM一个文档&#xff0c;适合LLM上下文大小不能容纳的小文档。 参考&#xff1a; https://js.langchain.com/v0.1…

搭建个人官网时如何配置SMTP邮件自动发送

什么是 SMTP&#xff1f; SMTP( Simple Mail Transfer Protocol ) 是一种简单邮件传输协议&#xff0c;可以在互联网上通过SMTP来发送电子邮件&#xff0c;是建模在 FTP 文件传输服务上的一种邮件服务&#xff0c;主要用于传输系统之间的邮件信息并提供来信有关的通知。SMTP 服…

pycharm不能安装包的解决方法

一直使用VScode写python&#xff0c;最近使用pycharm&#xff0c;但是pycharm不能安装包&#xff0c;类似这种 后面直接使用ALT F12跳转终端&#xff1a; pip install 需要添加的包 -i https://pypi.tuna.tsinghua.edu.cn/simple不报错了

量检具管理有一套

量检具是用于测量和检验产品尺寸、形状和质量的工具。有一位年轻的工程师小张&#xff0c;他负责管理工厂的量检具&#xff0c;确保它们能够准确地测量产品尺寸和质量。有一天&#xff0c;小张发现量检具出现了一些问题。他注意到一些量具的读数不准确&#xff0c;导致生产出来…

【吊打面试官系列-Mysql面试题】NULL 是什么意思?

大家好&#xff0c;我是锋哥。今天分享关于 【NULL 是什么意思&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; NULL 是什么意思? 答&#xff1a;NULL 这个值表示 UNKNOWN(未知):它不表示“”(空字符串)。对 NULL 这个值的任何比较都会生产一个 NULL 值。您不能…

ABAP - SALV SET_ZERO方法不显示金额0.00

财务觉得报表上的金额为0的数据混淆视线&#xff0c;所以提出了报表不显示0.00的格式要求。 要求报表是这个样&#xff1a; SALV提供了 cl_salv_column_table->set_zero() 来进行控制金额0.00是否显示 实现SALV不显示金额0.00关键代码&#xff1a; DATA:lo_columns TYPE …

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装&#xff0c;可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 &#xff08;1&#xff09;通过position属性,可以控制下拉选项的位置 &am…

注塑件检测视觉检测中可能遇到的外观缺陷

机器视觉检测注塑件不良特征有哪些&#xff1f;按照检测需求一般分为两类&#xff1a;外观缺陷和尺寸缺陷。但由于注塑件的工艺特点及原材料特性&#xff0c;注塑件外观缺陷在生产过程中出现的概率于频率远远大于尺寸缺陷。 注塑件检测视觉检测中可能遇到的外观缺陷 1、色差&a…

竞赛选题 python+opencv+深度学习实现二维码识别

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; pythonopencv深度学习实现二维码识别 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 该项目较为新颖&…

Vue核心指令解析:探索MVVM与数据操作之美

文章目录 前言一、Vue.js1. MVVM模式介绍2. 单页面组件介绍及案例讲解3. 插值表达式介绍及案例讲解 二、Vue常用指令详解1. 数据绑定指令v-textv-html 2. 条件渲染指令v-ifv-show 3. 列表渲染指令v-for循环数组介绍及案例讲解循环对象介绍及案例讲解 4. 事件监听指令v-on事件修…