首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

软件方法(下)第8章分析之分析类图—知识篇Part13-警惕拼凑泛化

很多书和文章中提到Liskov替换原则时,会以矩形和正方形(有时会换成椭圆和圆)的问题为例。 假设把正方形看作矩形的子类,如图8-107。...如果用正方形代替矩形,要么为了保持正方形的约束,最终得到的面积是5×5=25,要么两边自由变化,正方形就不再是正方形了。...如果独立描述矩形和正方形所需的属性,可以得到图8-108。 图8-108 建模矩形和正方形的属性 从图8-108可以得知,正方形的属性比矩形还少一个,把正方形作为矩形的子类是不合适的。...反过来,矩形倒是更像正方形的子类,复用边长,再加一个边长。...正方形、黄金分割矩形等没有增加新的属性,只是要求A边长和B边长的值符合某个约束,也就是说,正方形、黄金分割矩形是属性值组合中的一个子集的表征,这个就是状态。如图8-111。

31510

《架构整洁之道》第 9 章 LSP:里氏替换原则

均为原创,读架构整洁之道的笔记。里氏替换原则:(LSP :Liskov Substitution Principle)。使用一个父类对象,替换成该父类对象的子类对象后,该程序不会发生异常。...按照业务切换实现类,业务是可以正常进行的,不会破坏程序的正确性,不会发生异常。最关键的是这两个实现类,可以直接替换掉License接口。这样就是符合LSP原则的。...图片正方形/长方形问题以下设计中,正方形/长方形问题,是一个著名的违反LSP的设计案例。图片可以看到,User调用Rectangle为获得长方形的面积,可设置宽高。...而正方形与长方形的设置宽高的逻辑并不一致,所以正方形错误的继承了Rectangle。如果使用Square,来替换掉Rectangle,就会发现错误。看下面的例子。Rectangle r = ......所以这是一个违反LSP的案例,正方形不该继承于或者说成为长方形的子类型。

28730
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    软件设计SOLID原则及示例

    - 目的:当需要对软件进行改动时,应当通过增加新的代码来实现,而不是修改现有的代码,从而减少引入错误的风险。 3....里氏替换原则(Liskov Substitution Principle, LSP) - 定义:子类必须能够替换其基类并保持软件的正确性。...请注意,这些例子是为了演示目的而简化的,实际项目可能会更复杂。 1. 单一职责原则 (SRP) 问题描述:一个类既负责处理用户登录逻辑,又负责记录日志。...开放封闭原则 (OCP) 问题描述:假设我们有一个形状绘制应用,最初只支持圆形和正方形的绘制。...里氏替换原则 (LSP) 问题描述:假设有一个`Rectangle`类,其子类`Square`(正方形)改变了`setWidth`和`setHeight`的行为以保持边长相等。

    15510

    面向对象的代码风格(下)

    面向对象思想,针对结构化编程的这些缺点,提出了著名的“开-闭”原则。意思是代码应该对添加开放,对修改关闭。能做到这个原则,是需要代码结构上利用面向对象的特性才能做到的。...但实际上这种想法可能会是错误的,正确的设计应该是规则约束少的为基类,规则约束多的为子类。 最著名的例子是矩形和正方形。日常观念中,矩形是比较通用的,而正方形是比较特殊的图形。...所以我们很容易把矩形设计成基类,而正方形设计成继承矩形的子类。...但是这就是一个错误的设计,因为如果用户以矩形的接口,去使用正方形的实例对象,调用了设置长度、宽度的方法时,其中的一个设置可能就是无效的,因为正方形不能接受不同的长度和宽度。这很容易产生逻辑错误。...正确的做法是把正方形作为基类,而矩形继承正方形类,这样“设置边长”的方法也可用于矩形。 我们在设计类的继承关系时,必须注意所谓“一般”和“特殊”的真实含义。

    76440

    一文搞懂SOLID原则(javascript)

    一个类都应该只对某一类职责负责。 需求变更/升级,往往需要通过更改职责相关的类来体现。如果一个类拥有多个职责,对于某一职责的更改可能会破坏其他耦合的职责,产生无法预期的破坏。...LSP(Liskov Substitution Principle)-里氏替换原则 LSP(Liskov Substitution Principle)里氏替换原则。...举个经典示例来解释:从数学概念上,正方形属于长方形的一种;代码实现上,我们可以 正方形 extends 长方形,在这种场景下,我们要确保对于正方形的实现不能破坏原有长方形逻辑。...多个专用的接口比一个通用接口好。一个类决不要实现不会用到的接口。所以,实现多个特定的接口比实现一个通用接口要好。 JavaScript 中没有接口,下述以 typescript 为例。...在传统的应用架构中,低层次的组件设计用于被高层次的组件使用,以此构建一个复杂系统。

    32010

    谈谈 SOLID 原则

    这是一个非常简单的例子。当您的应用程序不断扩展并变得复杂时,您将看到,每次在整个应用程序中添加新动物时,都会在AnimalSound函数中使用if语句一遍又一遍地重复编写逻辑。...因为如果我们想给不同客户提供差异化的折扣时,你将要不断地修改Discount类的代码以添加新逻辑。 为了遵循开闭原则,我们将添加一个新类来继承Discount。...扩展就无需修改原本的代码啦。 里氏替换原则 里氏替换原则(Liskov Substitution Principle):子类必须可以替代其父类。 该原理的目的是确定子类可以无错误地占据其父类的位置。...,ISquare仅处理正方形的图形,IRectangle处理矩形的图形。...当然,还有另一个设计是这样: 类(圆形,矩形,正方形,三角形等)可以仅从IShape接口继承并实现其自己的draw行为,如下所示。

    62300

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

    违背 LSP 原则的一个简单示例 一个非常明显地违背 LSP原则的示例就是使用 RTTI(Run Time Type Identification)来根据对象类型选择函数执行。...既然这样,我们可能得出结论了,这个模型现在是自洽的(self-consistent)和正确的。但是,这个结论其实是错误的。一个自洽的模型不一定对它的所有用户都保持一致!...逻辑自洽性也要求构建理论过程中的所有逻辑推理和数学演算正确无误。逻辑自洽性是一个理论能够成立的必备条件。)...这个函数对 Rectangle 是可以工作的,但是如果传递一个 Square 参数进去则会发生断言错误。...这些函数揭示了对 LSP 原则的违背。此外,Square 从 Rectangle 衍生也破坏了这些函数,所以也违背了 OCP 原则。 有效性不是内在的 这引出了一个非常重要的结论。

    92030

    【愚公系列】2021年12月 面向对象设计原则(三)-里氏替换原则(Liskov Substitution Principle or LSP)

    文章目录 前言 一、里氏替换原则(Liskov Substitution Principle or LSP) 二、使用步骤 示例 总结 前言 常用的面向对象设计原则有七个,这七大设计原则都是以可维护性和可复用性为基础的...在代码中将基类对象转换成其子类对象,不应当产生任何错误或异常。...二、使用步骤 示例 namespace Liskov; public abstract class Shape { public abstract double Area(); public...里氏替换原则要求尽可能的使用其基类作为方法的参数,以下给出一个解决方案以供参考: public static void DoSomething(Shape shape) { var area...例如增加一个新的正方形子类Square,而不需要对DoSomething方法做任何改动。

    21010

    用 SOLID 原则保驾 React 组件开发

    ,这里想在库存为 0 时做出提示,但是逻辑和增减数字糅杂在了一起;如果想在项目中其他地方只想复用一个数字步进器,就要额外捎上很多其他不相关的业务逻辑,这显然是不合理的。...自己定义的组件也应该谨记这一原则,比如在一个 里包裹 ,并通过修改 props 来实现扩展按钮颜色的功能,而非直接找到 Button 的源码并增加颜色逻辑。...另外,“单一职责”中的两个例子也可以很好地解释“开放/封闭”原则,职责单一的情况下,通过继承或包裹就可以扩展新功能;反之就还要回到原模块的源代码中修修补补,让局势更混乱。...,上面的代码就产生了歧义;并且关键在于,如果基于现有的 API(允许分别设置宽高)有一个 “设置宽2高5就能得到面积10” 的假设,则正方形子类就无法实现该假设,而这样的实现就是违背里氏替换原则的不良实践...再举一个直观点的例子就是:如果一个地方放置了一个 Modal 弹窗,且该弹窗右上角有一个可以关闭的 [close] 按钮;那么无论以后在同样的位置替换 Modal 的子类或是用 Modal 包裹组合出来的组件

    82720

    面向对象设计的五项基本原则

    对一个事物抽象化,实质上是对一个事物进行概括、归纳、总结,将其本质特征抽象地用一个类来表示,这样类才会相对稳定,无需更改。 所谓扩展开放,就是在不改变已存在的类的前提下可以添加很多功能。...Liskov替换原则的作用就是为了保证继承复用的可靠。 下面来举个违反替换原则的特殊例子: 正方形与长方形的问题也是属于“圆不是椭圆”这类问题。...我们知道正方形是一个特殊的长方形,所以可以设计两个类,正方形类继承自长方形类。长方形类有两个成员变量,分别表示长和宽,有个计算面积的成员函数。假如计算面积的方法是virtual的,这样能实现多态。...所以一个正方形类继承自长方形类的设计是不好的(注意的一点是你违反了Liskov替换原则并不是说就写的代码就会出错,只是说设计不太合理。...单一职责原则与接口分离原都体现了内聚的思想; (2)开放封闭原则,要求类不作修改而能够扩展功能,体现了类的封装与继承; (3)Liskov替换原则,要求派生类要能够替换基类,是对类继承的规范;

    99220

    写了这么多年代码,你真的了解SOLID吗?| 洞见

    利益相关者角色是一个重要的变化原因,不同的角色会有不同的需求,从而产生不同的变化原因。作为居民,家用的电线是普通的220V电线,而对电网建设者,使用的是高压电线。...用一个Wire类同时服务于两类角色,通常意味着坏味道。 变更频率是另一个值得考虑的变化原因。即使对同一类角色,需求变更的频率也会存在差异。...,最典型的例子就是Bob大叔在《敏捷软件开发:原则、模式与实践》中讲到的正方形继承矩形的例子了。...从一般意义来看,正方形是一种矩形,但这种继承关系破坏了业务的正确性。...如果r是一个正方形,则面积为16 } 代码中testArea方法的参数如果是正方形,则面积是16,而不是期望的20,所以结果显然不正确了。

    83310

    设计模式 - 六大设计原则之LSP(里氏替换)

    是动作正确性的保证,即类的扩展不会给已有系统引入新的错误,降低了代码出错的可能性 加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需求变更时引入的风险。...---- Case 关于里氏替换的场景,最有名的就是“正方形不是长方形” , 当然了还有一些关于动物的例子,比如鸵鸟、企鹅都是鸟,但是不会飞。...这样的例子可以非常形象的帮助我们理解里氏替换中关于两个类的继承不能破坏原有特性的含义。 这里我们用个银行卡的场景来描述一下: 储蓄卡、信用卡都可以消费,但信用卡不宜提现,否则产生高额利息。...此时继承父类实现的信用卡的类并不满足里氏替换的原则。 也就是说,此时的子类不能承担原父类的功能,直接给储蓄卡使用。...实现这样的类的最好的方式就是提取出一个抽象类 , 由抽象类定义所有卡的共同核心属性、逻辑, 把卡的支付和还款等动作抽象成正向和逆向操作。

    52230

    以对象为中心和MDL原则处理ARC挑战 2023

    一个任务模型M = (Mi, Mo)由一个输入网格模型Mi和一个输出网格模型Mo组成。图2显示了一个正确的任务b94a9452的模型,用文字表述为:“输入网格中有两个堆叠的完整矩形,背景为黑色。...这些泛化在ARC任务的测试示例中并不是必需的,但它们使模型能够在打破训练示例不变量的输入网格上工作,例如,一个十字形在一个矩形上方,矩形在一个蓝色背景上方。...在程序合成领域的一项著名工作[13]导致了Microsoft Excel 2013的一个新功能,称为FlashFill。...,输出字符串可以是天或年份的最后两位数字;在任务11中,训练示例有一个打字错误(故意的),这使得任务未指定。...输出是这三个整数的连接,用破折号分隔,当输入中缺少第一个整数时,它是425。在FlashFill中,通常会产生大量的程序,因为执行的是穷举搜索。

    12810

    软件架构设计原则--里氏替换原则

    本专栏内容参考自:咕泡学院Tom老师的《Spring5核心原理与30个类手写实战》,仅作个人学习记录使用,如有侵权,联系速删   里氏替换原则(Liskov Substitution Principle...可以理解为一个软件实体如果适用于一个父类,那么一定适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类的对象能替换父类的对象,而程序逻辑不变。   ...用一个经典的业务场景:用正方形、矩形、和四边形的关系说明里氏替换原则,我们都知道正方形是一个特殊的长方形,所以可以创建一个父类Rectangle: public class Rectangle {...我们再来创建一个基于长方形和正方形共同的抽象四边形接口Quadrangle: public interface Quadrangle { long getWidth(); long getHeight...Quadrangle,方法内部就会报错,因为正方形已经没有了设置宽高的方法。

    34030

    SOLID之LSP

    里氏代换原则 LSP,Liskov Substitution Principle 子类型必须能够替换掉它们的基类型 若对每个类型S的对象O1,都存在一个类型T的对象O2,使得在所有针对T编写的程序P中,...用O1替换O2后,程序P行为功能不变,则S是T的子类型 LSP是继承关系设计基本原则,也是使OCP成为可能的主要原则之一。...同样假设B的某个派生类D,如果把D对象作为B类型传递给f,会导致f出现错误的行为。那么D就违反了LSP。显然,D对于f来说是脆弱的。...IS-A关系,那么这个新对象的类应该从这个已用对象的类派生 从一般意义上讲,一个正方形就是一个矩形。...因此,把Sequare类视为从Rectangle类派生是合乎逻辑的 void f(Rectangle r) { r.setWidth(5); r.setHeight(4); assert

    71430

    为什么一个类不能随意被继承?

    今天我们来聊聊S.O.L.I.D原则中的L:Liskov Substitution Principle(LSP),里氏替换原则。...里氏替换原则(Liskov Substitution Principle,LSP)可以解释为: 派生类型(子类)必须能够替换掉它们的基类型(父类)。...从语法上来说,怎么用 extends 关键字来实现父子类关系都可以!但从业务逻辑上看,这是有很大问题的。比如下面这个例子。 LSP 反证示例 我们有个 Dog 类。...同样,网络上经典的例子:正方形不是长方形的子类,也是如此。 大多数小伙伴觉得正方形可以继承长方形,是因为把长和宽设置为一样就成正方形了。代码语法层面上很好实现。...问题在于,如果一个程序需要长方形进行面积计算时,你用正方形来替代,计算出的结果就和预期不符了。

    20920

    软件架构设计原则之里氏替换原则

    里氏替换原则(Liskov Substitution Principle,LSP)是指如果对每一个类型为T1的对象o1,都有类型为T2的对象O2,使得以T1定义的所有程序P在所有的对象O1都替换成O2时...可以理解为一个软件实体如果适用于一个父类,那么一定适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。...在讲开闭原则的时候我埋下了一个伏笔,在获取折扣时重写覆盖了父类的getPrice()方法,增加了一个获取源码的方法getOriginPrice(),显然就违背了里氏替换原则。...现在来描述一个经典的业务场景,用正方形、矩形和四边形的关系说明里氏替换原则,我们都知道正方形是一个特殊的长方形,所以就可以创建一个父类Rectangle: public class Rectangle...我们再来创建一个基于长方形与正方形共同的抽象四边形接口Quadrangle: public interface Quadrangle { long getWidth(); long

    44520

    软件方法(下)分析和设计第8章分析 之 分析类图——知识篇(20211227更新)

    很多书和文章中提到Liskov替换原则时,会以矩形和正方形(有时会换成椭圆和圆)的问题为例。 假设把正方形看作矩形的子类,如图8-90。...如果用正方形代替矩形,要么为了保持正方形的约束,最终得到的面积是5×5=25,要么两边自由变化,正方形就不再是正方形了。...图8-91 建模矩形和正方形的属性 从图8-91可以得知,正方形的属性比矩形还少一个,把正方形作为矩形的子类是不合适的。 反过来,矩形倒是更像正方形的子类,复用边长,再加一个边长。...也可以把A边长和B边长属性保留在矩形中,正方形、黄金分割矩形如果适用特殊的规则,可以作为矩形的状态。...正方形、黄金分割矩形等没有增加新的属性,只是要求A边长和B边长的值符合某个约束,也就是说,正方形、黄金分割矩形是属性值组合中的一个子集的表征,这个就是状态。如图8-94。

    1.2K50

    C++ 继承与组合的区别

    比如在OO界中著名的“鸵鸟不是鸟”和“圆不是椭圆”的问题。这样的问题说明了程序设计和现实世界存在逻辑差异。...类继承允许我们根据自己的实现来覆盖重写父类的实现细节,父类的实现对于子类是可见的,所以我们一般称之为白盒复用。继承易于修改或扩展那些被复用的实现,但它这种白盒复用却容易破坏封装性。...所以我们要经的起“继承”的诱惑,避免犯下设计错误。...而缺点就是致使系统中的对象过多。 综上所述,Is-A关系用继承表示,Has-A关系用组合表示,GoF在《设计模式》中指出OO设计的一大原则就是:优先使用对象组合,而不是类继承。...而在椭圆和圆的问题上,椭圆类中的成员函数setSize(x,y)违背了这个可置换性,即Liskov替换原则。 所有不良继承都可以归结为“圆不是椭圆”这一著名具有代表性的问题上。

    62910

    【GAMES101-现代计算机图形学课程笔记】Lecture 09 Shading 3 (纹理映射)

    这样一来,比如A纹理原来的大小是100x100,B纹理原来的大小是20x20,很显然映射后A所对应的纹理平面的纹理会更密集,而B则会相对稀疏。...Mipmap之所以会产生模糊效果正是因为正方形近似导致的。我们通过下图可以看到左边的屏幕空间的每个像素对应到右边的纹理空间的形状可能是不规则的扁、长的形状,如果用正方形取近似显然会导致很大的误差。...Mipmap得到的一系列的纹理图其实就是对角线上的卫星,可以看到都是正方形的,而各向异性过滤会对把原纹理图缩放成不同大小的矩形,各向异性生成的一系列纹理图也叫Ripmaps。...这样处理之后,当查询屏幕空间某个像素点的纹理时,我们就可以用其对应的纹理图上的纹理,这样就解决了Mipmap只能用正方形来近似的问题。...但是各向异性过滤只是解决了规则的矩形的映射问题,还是没法解决那些非常不规则的图形,比如上图的纹理图中的斜着的矩形。

    2.3K80
    领券