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

设计模式原则

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

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

  • 在这里插入图片描述

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

在这里插入图片描述

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于电机的线性思考

当大多数工程师听到电机这个词时&#xff0c;他们自然地想到旋转装置&#xff0c;例如有刷直流、无刷直流、步进电机或变频原动机。但是电机不一定是旋转的&#xff0c;很多时候设计需要直线运动。一种解决方案是添加某种齿轮或皮带装置来转换旋转运动&#xff0c;这种解决方案…

GPU技术全景:推动未来计算的新动力-1

1、概述 主流GPU技术方向在近年来持续快速发展&#xff0c;聚焦于提升性能、能效、灵活性以及适应不断增长的计算需求&#xff0c;尤其是在人工智能、高性能计算、图形渲染、数据分析以及虚拟现实等领域。以下是几个关键的发展趋势和方向&#xff1a; 1. 并行计算优化&…

基于Java校园短期闲置资源置换平台设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

计算机方向国际学术会议推荐

【JPCS独立出版 | EI核心、Scopus】第四届计算机、遥感与航空航天国际学术会议&#xff08;CRSA 2024&#xff09; 大会官网&#xff1a;www.iccrsa.org 时间地点&#xff1a;2024年7月5-7日&#xff0c;日本-大阪&#xff08;线上召开&#xff09; 征稿主题&#xff1a;计算…

Oracle数据库的安装

1.下载压缩包 2.双击setup.exe

数字化时代的网站优化利器:三大API服务深度解析

数字化时代的网站优化利器&#xff1a;三大API服务深度解析 在当今数字化飞速发展的时代&#xff0c;网站的优化与监控对于企业和个人的在线业务至关重要。2024 年 06 月 24 日 15 点 11 分 05 秒&#xff0c;星期一&#xff0c;我们正处在一个竞争激烈的网络环境中&#xff0…

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

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

Qt项目天气预报(6) - 引入QMap: debug+更新天气图片

QMAP 解决bug (&#xff09; bug描述 由于json文件中有的地方不带市&#xff0c;有的地方带县&#xff0c;有的地方是区&#xff0c;我们匹配不上这个地方&#xff0c;我们可以使用QString进行字符串拼接来实现。 另外&#xff0c;我们之前的 getCityCodeFromName()函数写得…

Screw - 数据库表结构文档生成器

Screw-自动化程度高&#xff0c;能快速生成文档&#xff0c;减少手动编写的工作量 支持多种数据库生成HTML、Word、MarkDown 三种格式的文档 快速上手&#xff0c;以Oracle方式为例 第一种方式&#xff1a;Maven 插件 1、引入 <build><plugins><plugin>&…

vue中图谱关系插件relation-graph

vue中图谱关系插件relation-graph 一、效果图二、安装下载&#xff08;vue2.0版本的&#xff09;三、直接上代码 一、效果图 二、安装下载&#xff08;vue2.0版本的&#xff09; npm install --save relation-graph var foo bar;三、直接上代码 <template><div cla…

LeetCode 热题100 --双指针

双指针 b站UP主蜜糖&#xff1a;由于数据特征的有序性&#xff08;大小或者正负&#xff09;&#xff0c;所以可以证明当前节点一定是优于过往节点&#xff0c;从而可以通过数据的维度数量的指针&#xff0c;逐步的迭代收敛最终找到最优解。 283.移动零 相关标签 &#xff1a;…

TypeScript(笔记版)

简介&#xff1a; nvm安装必须先把自己的node卸了&#xff0c;再去安装nvm TS就是js的超集 对js进行了扩展 浏览器不支持ts&#xff0c;要转换为js才可以。 ts是用来编程人员爽的 js的写法拿到ts也可以&#xff0c;ts代码量更大&#xff0c;但ts代码更加清晰 可以在playg…

数显胎压计方案采用SIC8632主控芯片

汽车作为现代出行的重要工具&#xff0c;极大地提升了人们的出行效率。随着生活品质的提升&#xff0c;越来越多的家庭拥有了私家车。然而&#xff0c;对于车主而言&#xff0c;掌握驾驶技巧只是基础&#xff0c;了解如何正确检测汽车胎压同样至关重要。胎压计&#xff0c;即气…

年化16.6%,全球大类资产使用lightGBM预测轮动——数据缓存提升效率

原创文章第568篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 Dataloader缓存 加载160个因子&#xff0c;10几支大类资产&#xff0c;这个计算还是需要一点时间&#xff0c;尤其在我们频繁运行的时候&#xff0c;需要等待&#xff0c;这里我们…

深入分析 Android BroadcastReceiver (六)

文章目录 深入分析 Android BroadcastReceiver (六)1. 广播机制的高级优化策略1.1 使用 Sticky Broadcast&#xff08;粘性广播&#xff09;示例&#xff1a;粘性广播&#xff08;过时&#xff0c;不推荐&#xff09; 1.2 使用 LiveData 和 ViewModel 进行组件通信示例&#xf…

dockercompose部署redis哨兵模式并集成springboot

第一步 编写compose文件 docker-compose.yml version: 3.8networks:redis-network:driver: bridgeservices:redis-master:image: redis:7.2.4container_name: redis-mastercommand: ["sh", "-c", "redis-server --protected-mode no --slave-announ…

[leetcode hot 150]第十一题,盛水最多的容器

题目&#xff1a; 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾…

基于Java实验室课程管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

小米录屏怎么录?教你2种方法轻松录屏

“最近新换的小米手机&#xff0c;但不知道怎样打开小米手机的录屏功能啊&#xff1f;而且有没有办法能录制到手机的高清画面啊&#xff1f;谁能教教我啊&#xff1f;” 随着科技的飞速发展&#xff0c;录屏功能逐渐成为我们手机使用中不可或缺的一部分。在众多录屏工具中&…

冲上热搜!太“上头”!除了这碗粉,它还坐拥“全球第一”!

千年前&#xff0c;唐代诗人柳宗元便与柳州结下不解之缘&#xff0c;通晓医理的他&#xff0c;竟然是螺蛳粉的初代“推广大使”&#xff1b;如今&#xff0c;柳州螺蛳粉全产业链一年狂揽近670亿元&#xff0c;还走出了国际范儿。 百年前&#xff0c;斜阳路的电灯点亮这座城市的…