第05篇 里氏代换原则

一、定义

里氏代换原则的定义有两种:

  • 完整定义
    如果对每一个类型为S的对 象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1代换o2时,程序P的 行为没有变化,那么类型S是类型T的子类型。这个定义比较拗口且难以理解。
  • 通俗版定义
    里氏代换原则(Liskov Substitution Principle, LSP):所有引用基类 (父类)的地方必须能透明地使用其子类的对象。

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对 象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用 子类对象来替换父类对象

二、特点

里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任 何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不 一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类;但是 我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。

注意事项:

  1. 子类的所有方法必须在父类中声明,或子类必须实现父类中声明的所有方法。根据里氏代 换原则,为了保证系统的扩展性,在程序中通常使用父类来进行定义,如果一个方法只存在 子类中,在父类中不提供相应的声明,则无法在以父类定义的对象中使用该方法。
  2. 我们在运用里氏代换原则时,尽量把父类设计为抽象类或者接口,让子类继承父类或实现 父接口,并实现在父类中声明的方法,运行时,子类实例替换父类实例,我们可以很方便地 扩展系统的功能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类 来实现。里氏代换原则是开闭原则的具体实现手段之一。
  3. Java语言中,在编译阶段,Java编译器会检查一个程序是否符合里氏代换原则,这是一个 与实现无关的、纯语法意义上的检查,但Java编译器的检查是有局限的

三、案例

公司开发的CRM系统中,客户(Customer)可以分为VIP客户(VIPCustomer)和普通 客户(CommonCustomer)两类

(一)初始方案

在这里插入图片描述

存在的问题

无论是普通客户还是VIP客户,发送邮件的过程都是相同的,也就是说两个send()方法中的代码重复,而且在本系统中还将增加新类型的客户。

(二)LSP优化

为了让系统具有更好的扩展性,同时减少代码重复,使用里氏代换原则对其进行重构。
可以考虑增加一个新的抽象客户类Customer,而将CommonCustomer和VIPCustomer类作为其子类,邮件发送类EmailSender类针对抽象客户类Customer编程,根据里氏代换原则,能够接受基类对象的地方必然能够接受子类对象,因此将EmailSender中的send()方法的参数类型改为Customer,如果需要增加新类型的客户,只需将其作为Customer类的子类即可。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值