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

news2024/10/7 20:29:18

设计模式原则

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

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重复
    */
   @Override
   public 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重复
    */
   @Override
   public String recharge(String orderId, BigDecimal amount) {
       // 模拟生成还款单
       logger.info("生成还款单,单号:{} 金额:{}", orderId, amount);
       // 模拟还款成功
       logger.info("还款成功,单号:{} 金额:{}", orderId, amount);
       return "0000";
   }

   @Override
   public 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);

   @Test
   public 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));
   }

   @Test
   public 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);

  @Test
  public 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));
  }

  @Test
  public 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.coloradmin.cn/o/1856809.html

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

相关文章

Clickhouse 的性能优化实践总结

文章目录 前言性能优化的原则数据结构优化内存优化磁盘优化网络优化CPU优化查询优化数据迁移优化 前言 ClickHouse是一个性能很强的OLAP数据库&#xff0c;性能强是建立在专业运维之上的&#xff0c;需要专业运维人员依据不同的业务需求对ClickHouse进行有针对性的优化。同一批…

用友 【U8+】供应链-暂估方式

【U8+】供应链-暂估方式 知识点:三种不同暂估方式的应用 应用场景: 对于采购业务如果货到票未到时,需要对采购入库进行估价入账,等收到发票时再按发票的成本核算采购入库成本。系统提供了三种暂估方式:月初回冲、单到回冲和单到补差。 操作流程: l 单到回冲 跨月全…

FreeCAD属性机制原理分析

1.实现原理 FreeCAD定义了一套属性层次结构&#xff0c;最上层是Property基类&#xff0c;该类主要提供了外部访问属性的接口及两个成员变量&#xff1a;属性名称、属性状态及属性容器类PropertyContainer。具体的属性直接或间接继承Property类&#xff0c;属性类中主要记录属性…

【机器学习】半监督学习可以实现什么功能?

目录 一、什么是机器学习二、半监督学习算法介绍三、半监督学习算法的应用场景四、半监督学习可以实现什么功能&#xff1f; 一、什么是机器学习 机器学习是一种人工智能技术&#xff0c;它使计算机系统能够从数据中学习并做出预测或决策&#xff0c;而无需明确编程。它涉及到…

Conda创建与激活虚拟环境(指定虚拟环境创建位置)

1.Conda优势 Conda是一个开源的软件包管理系统和环境管理系统&#xff0c;主要用于在不同的计算环境中安装和管理软件包和其依赖项。它最初是为Python而设计的&#xff0c;但现在也可以用于管理其他语言的软件包。 Conda提供了对虚拟环境的支持&#xff0c;这使得用户可以在同…

想拥有一个独一无二的AI人物?Lora炼丹训练模型教程来啦

之前答应过大家放出来的Lora本地训练教程&#xff0c;终于写好啦。 会训练lora&#xff0c;代表着你可以生成属于你的独一无二的角色。 你可以让这个角色在各种不同背景的地方出现&#xff0c;可以让它摆出各种姿势&#xff0c;满足你的无限幻想。 还有的商家&#xff0c;用…

java之SSRF代码审计

1、SSRF漏洞审计点 服务端请求伪造&#xff08;Server-Side Request Forge&#xff09;简称 SSRF&#xff0c;它是由攻击者构造的 payload传给服务端&#xff0c;服务端对传回的 payload 未作处理直接执行后造成的漏洞&#xff0c;一般用于在内网探测或攻击内网服务。 利用&a…

Graalvm尝鲜使用

面试时遇到大佬提点了下在性能不足的机器上传统优化JVM调优已经作用不大的背景下&#xff0c;采用graalvm进行打包成二进制文件&#xff0c;脱离java虚拟机&#xff0c;性能提升20%到100%&#xff0c;因此实操记录下来&#xff0c;方便后续使用 1、前置预装 graalvm-ce-java17…

qt开发-12_QScrollArea

在 Qt 中&#xff0c;QScrollArea 是用于显示可以滚动内容的控件&#xff0c;通常用于处理视图中内容超出可见区域的情况。它提供了一种在有限的视窗内显示大量内容的解决方案&#xff0c;如显示大图像、长文本、多个小部件等。 常用方法和属性 setWidget(QWidget *widget)&am…

android在线阅读代码网站

android在线阅读代码社区&#xff1a; Android 1.6 到 Android 10 的源码&#xff1a; Android OS 在线源代码 - https://www.androidos.net.cn10.0.0_r6 - Android社区 - https://www.androidos.net.cn/ AndroidXRef https://cs.android.com/ https://cs.android.com/android…

容器之视角构件的演示

代码&#xff1a; #include <gtk-2.0/gtk/gtk.h> #include <glib-2.0/glib.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <stdio.h>int main(int argc, char *argv[]) {gtk_init(&argc, &argv);GtkWidget *window;window gtk_window_ne…

Shopline电商平台的对接流程

对接Shopline平台需要具备一定的技术能力&#xff0c;包括API开发经验、编程技能以及对电商平台运作的理解。此外&#xff0c;与Shopline平台的技术支持团队保持沟通&#xff0c;可以在遇到问题时获得帮助。对接Shopline平台的流程通常涉及以下关键步骤。 1.了解Shopline API文…

详解大模型是如何理解并使用 tools ?

前文 大家肯定对使用大模型的函数回调或者说 Tools 已经耳熟能详了&#xff0c;那么他们具体内部是如何运作的呢&#xff0c;本文就此事会详细给大家介绍具体的细节。 tools 首先是大家最熟悉的环节&#xff0c;定义两个 tool 的具体实现&#xff0c;其实就是两个函数&#…

WSL+Anconda(pytorch深度学习)环境配置

动机 最近在读point cloud相关论文&#xff0c;准备拉github上相应的code跑一下&#xff0c;但是之前没有深度学习的经验&#xff0c;在配置环境方面踩了超级多的坑&#xff0c;依次来记录一下。 一开始我直接将code拉到了windows本地来运行&#xff0c;遇到了数不清的问题&a…

数据分析:置换检验Permutation Test

欢迎大家关注全网生信学习者系列&#xff1a; WX公zhong号&#xff1a;生信学习者Xiao hong书&#xff1a;生信学习者知hu&#xff1a;生信学习者CDSN&#xff1a;生信学习者2 介绍 置换检验是一种非参数统计方法&#xff0c;它不依赖于数据的分布形态&#xff0c;因此特别适…

99.9% 超高控制精度!混合量子芯片具备大规模生产潜力

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨沛贤/浪味仙 排版丨沛贤 深度好文&#xff1a;700字丨5分钟阅读 摘要&#xff1a;悉尼量子初创公司 Diraq 正与一个欧洲研发联盟展开合作&#xff0c;通过将量子比特与传统晶体管结合&…

新能源汽车 LabCar 测试系统方案(二)

什么是LabCar测试 LabCar测试目标是进行整车黄板台架功能测试&#xff0c;用于整车开发和测试阶段&#xff0c;满足设计人员和测试人员的试验需求&#xff0c;以验证整车性能&#xff0c;减少开发工作量。系统主要用于测试静态及动态工况下的纯电动汽车的各项功能实现情况。 …

股票分析学习

库&#xff1a; pandas to_datetime:它可以处理各种格式的日期和时间数据&#xff0c;并将其统一转换为 Pandas 可以理解和操作的内部日期时间格式。 matplotlib.pyplot 用户可以轻松地创建各种静态、动态、交互式和 3D 图形。 1. 绘制线图&#xff08;plot()&#xff09; …

eVTOL飞机:技术挑战、应用机遇和运动的作用

最近&#xff0c;航空业的嗡嗡声围绕着电动空中出租车、空中拼车、无人驾驶航空货物运送等。这些概念都依赖于一类称为eVTOL的飞机&#xff0c;eVTOL是电动垂直起降的缩写。 与直升机类似&#xff0c;但没有噪音和排放&#xff0c;eVTOL可以在不需要简易机场的情况下飞行、悬停…

Python | Leetcode Python题解之第171题Excel列表序号

题目&#xff1a; 题解&#xff1a; class Solution:def titleToNumber(self, columnTitle: str) -> int:number, multiple 0, 1for i in range(len(columnTitle) - 1, -1, -1):k ord(columnTitle[i]) - ord("A") 1number k * multiplemultiple * 26return n…