03 里氏替换原则

news2025/1/16 3:42:39
官方定义:

里氏替换原则(Liskov Substitution Principle,LSP)是由麻省理工学院计算机科学系教授芭芭拉·利斯科夫于 1987 年在“面向对象技术的高峰会议”(OOPSLA)上发表的一篇论文《数据抽象和层次》(Data Abstractionand Hierarchy)里提出的.
她在论文中提到:如果S是T的子类型,对于S类型的任意对象,如果将他们看作是T类型的对象,则对象的行为也理应与期望的行为一致

子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。

如何理解里氏替换原则?

要理解里氏替换原则,其实就是要理解两个问题:
什么是替换?
什么是与期望行为一致的替换(Robert Martin所说的“必须能够替换”)?

1 ) 什么是替换 ?
替换的前提是面向对象语言所支持的多态特性,同一个行为具有多个不同表现形式或形态的能力。
在这里插入图片描述
2 ) 什么是与期望行为一致的替换?
在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类的实现,都与接口或基类方法的期望行为一致。

不需要关心是哪个类对接口进行了实现,因为不管底层如何实现,最终的结果都会符合接口中关于方法的描述(也就是与接口中方法的期望行为一致).
或者说接口或基类的方法是一种契约,使用方按照这个契约来使用,派生类也按照这个契约来实现。这就是与期望行为一致的替换。

场景案例

比如在一个商城项目中,有3种促销活动:
1)PromotionalStrategy (满减活动,两百以上百八折)
2)RebateStrategy(打折活动)
3)ReduceStrategy(返现活动)
在这里插入图片描述

public interface Istrategy {
	public double realPrice(double consumePrice);
}
public class PromotionalStrategy implements Istrategy {
	public double realPrice(double consumePrice) {
if (consumePrice > 200) {
return 200 + (consumePrice - 200) * 0.8;
} else {
return consumePrice;
}
}
}
public class RebateStrategy implements Istrategy {
private final double rate;
public RebateStrategy() {
this.rate = 0.8;
}
public double realPrice(double consumePrice) {
return consumePrice * this.rate;
}
}
public class ReduceStrategy implements Istrategy {
public double realPrice(double consumePrice) {
if (consumePrice >= 1000) {
return consumePrice - 200;
} else {
return consumePrice;
}
}
}

调用方为Context,在此类中使用接口定义了一个对象

public class Context {
//使用基类定义对象变量
private Istrategy strategy;
// 注入当前活动使用的具体对象
public void setStrategy(Istrategy strategy) {
this.strategy = strategy;
}
// 计算并返回费用
public double cul(double consumePrice) {
// 使用具体商品促销策略获得实际消费金额
double realPrice =
this.strategy.realPrice(consumePrice);
// 格式化保留小数点后1位,即:精确到角
BigDecimal bd = new BigDecimal(realPrice);
bd = bd.setScale(1, BigDecimal.ROUND_DOWN);
return bd.doubleValue();
}
}

Context 中代码使用接口定义对象变量,这个对象变量可以是实现了lStrategy
接口的PromotionalStrategy、RebateStrategy 、 ReduceStrategy任意一个。

里氏代换原则与多态的区别 ?

虽然从定义描述和代码实现上 来看,多态和里式替换有点类似,但它们关
注的角度是不一样的。多态是面向对象编程的一 大特性,也是面向对象编
程语言的一种语法。它是一种代码实现的思路。而里式替换是一种 设计原
则,用来指导继承关系中子类该如何设计,子类的设计要保证在替换父类
的时候,不 改变原有程序的逻辑及不破坏原有程序的正确性。

里氏替换原则和依赖倒置原则,构成了面向接口编程的基础,正因为里氏替换
原则,才使得程序呈现多样性。

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

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

相关文章

02 开闭原则

官方定义: 开闭原则规定软件中的对象、类、模块和函数对扩展应该是开放的,但对于修 改是封闭的。这意味着应该用抽象定义结构,用具体实现扩展细节,以此确保 软件系统开发和维护过程的可靠性。 通俗解释: 对扩展开放…

什么是广告学?什么是广告理论?

想当年,我在众多的专业中选择了广告学,幻想着以后的激情岁月,拿着电脑,出入各种写字楼和同伴时不时拽两句英文。 来后,我也没发现学广告学能有什么远大的理想,满满当当的排课表上有广告学概论、市场营销学…

Go 泛型解密:从基础到实战的全方位解析

Go泛型解密 一、概述 泛型编程是计算机科学中一个相当重要的概念,广泛应用于各种编程语言和框架中。在Go语言中,泛型的讨论和实现也走了一段相对漫长的路。这一路上既有激烈的讨论,也有种种的尝试和迭代。本节将对泛型的基础概念进行深入分析…

看了我项目中购物车、订单、支付一整套设计,同事也开始悄悄模仿了...

在我的mall电商实战项目中,有着从商品加入购物车到订单支付成功的一整套功能,这套功能的设计与实现对于有购物需求的网站来说,应该是一套通用设计了。今天给大家介绍下这套功能设计,涵盖购物车、生成确认单、生成订单、取消订单以…

【Proteus仿真】【Arduino单片机】LED

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用LED等。 主要功能: 系统运行后,LED花样显示。 二、软件设计 /* 作者:嗨小易(QQ:3…

Arcgis聚合工具——实现简单的升尺度

找到Aggregate工具 按如下设置进行操作 注意:如有需要对应的低分辨率影像,必须点开右下角环境Environments选项,进行栅格的捕捉选项设置,以防止升尺度后的影像与需对应的低分辨率影像的栅格单元存在偏移。 点击OK,即可…

Linux CentOS 8(网卡的配置与管理)

Linux CentOS 8(网卡的配置与管理) 目录 一、项目介绍二、命令行三、配置文件四、图形画界面的网卡IP配置4.1 方法一4.2 方法二 一、项目介绍 Linux服务器的网络配置是Linux系统管理的底层建筑,没有网络配置,服务器之间就不能相互…

内核IO栈 | IO缓冲区的向下传递过程

最近遇到个这么一个事,查阅SCSI手册,对于READ(10)命令,似乎在采用DMA的情况下,下发的SCSI命令中,并没有内存空间的地址和长度: 也就是说,单纯从这一个命令中,我们并不知道将数据从硬…

MyBatis源码初始

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: MyBatis源码解读 ✨特色专栏&#xff…

首饰上亚马逊合规认证RSL报告

首饰 首饰是一种古老而又流行的装饰品,它们不仅可以点缀女性的美丽,还可以表达个人的品味和风格。首饰的种类繁多,有耳环、项链、手镯、戒指等,每一种都有自己的特点。 随着人们对珠宝首饰的要求越来越高,为了确保珠宝…

uni-app小程序使用DCloud(插件市场)流程

一、DCloud(插件市场) DCloud 是uni-app官方插件市场,里面有官方、团队、个人发布的众多插件,包括uni-ui、uni-pay 等。而像uni-ui这种大型组件库都有官方文档可参考,但一些团队或个人发布的小型插件没有文档&#xf…

Python调用c++生成的dll

Python调用c生成的dll 1.简单例子1.1 vs2019 c生成dll1.2 Python端调用 2.调用c类生成的dll2.1 vs cpp端生成dll2.2 Python端调用 参考文献 1.简单例子 1.1 vs2019 c生成dll 项目中添加add.cpp文件 extern "C" int __declspec(dllexport) add(int x, int y) {retu…

SpringBoot + Disruptor 实现特快高并发处理,支撑每秒 600 万订单无压力!

背景 工作中遇到项目使用Disruptor做消息队列,对你没看错,不是Kafka也不是rabbitmq。Disruptor有个最大的优点就是快,还有一点它是开源的哦,下面做个简单的记录。 Disruptor介绍 Disruptor 是英国外汇交易公司LMAX开发的一个高…

中国式复杂报表制作工具及技巧,解决90%效率问题

最大的数据杀手——中国式复杂报表 作为资料人,在日常生活和工作之中,我们是否经常被要求制作如下图所示的一些数据统计表格: 总的来看,很多人经常发现自己虽然有数据,却不知道用什么图表来进行数据最佳形式的价值表…

「我在淘天做技术」一篇文章告诉你商品团队在做哪些有意思的事?

作者:许令波(君山) 近期淘天集团秋季 2024 届校园招聘正式启动,预计将发放 2000 多个 offer,其中技术类岗位占比超过 50%。为了方便大家更真实地了解淘天技术的布局和现状,我们策划了「我在淘天做技术」系列,首次全面分享淘天技术…

【限时优惠】RHCE9.0培训考证-红帽官方授权中心

【微|信|公|众|号:厦门微思网络】 官网: www.xmws.cn 相信关注红帽认证的小伙伴都已经知道了:2022 年 5 月 18 日,红帽公司宣布推出红帽企业 Linux 9 (RHCE 9),这是世界领先的企业 Linux 平台的最新版本。 特别提醒的是…

怎样成功部署CRM销售管理系统?

部署CRM销售管理系统可以是自上而下的落实,也可以自下而上让基层员工提出他们的建议,毕竟他们才是系统的使用者。成功部署CRM销售管理系统离不开以下几点要素: 1、全渠道沟通 在通讯技术发达的今天,人们可以在任何地方进行视频通…

Unity3D Shader新手入门教程:3D溶解与腐蚀特效详解

引言 在游戏开发中,特效是非常重要的一部分,它能够增加游戏的趣味性和可玩性。其中,Shader特效是一种非常常见和常用的特效,它能够通过改变物体表面的渲染方式来实现各种各样的特效效果。本文将详细介绍Unity3D中的Shader 3D溶解与…

华为云应用中间件DCS系列—Redis实现(电商网站)秒杀抢购示例

云服务、API、SDK,调试,查看,我都行 阅读短文您可以学习到:应用中间件系列之Redis实现(电商网站)秒杀抢购示例 1 什么是DEVKIT 华为云开发者插件(Huawei Cloud Toolkit)&…

游戏设计模式专栏(十二):在Cocos游戏开发中运用代理模式

点击上方亿元程序员关注和★星标 引言 大家好,我是亿元程序员,一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》,让糟糕的代码在潜移默化中升华,欢迎大家关注分享收藏订阅。 代理模式&#xff08…