设计原则--里氏替换原则

哪些代码是违反里氏替换原则的?

如何将代码改造成满足里氏替换原则?

里氏替换原则和多态的区别?

 

相比其他的设计原则,里氏替换原则还是比较简单,比较容易理解和掌握的。

里氏替换原则,英文名Liskov Substitution Principle,缩写LSP。子类对象能够替换程序中父类对象出现的任何地方,并且保证原有程序的逻辑行为不变,及正确性不发生改变。

看到这里是不是觉得多态和里氏替换原则有点相似呢?先进一步解读里氏替换原则,然后再区分二者得区别。实际上,里氏替换原则还有一个更加落地,更有指导意义得描述,那就是“Design By Contract”,中文翻译是“按照协议来设计”。也就是说,子类再设计的时候,要遵循父类的行为约定(或者协议),那子类可以改变函数的内部逻辑,但不能改变函数原有的行为约定,这里的行为约定包括:函数声明要实现的功能,对输入、输出、异常的约定,甚至包括注释中所罗列的任何特殊说明。定义中父类和子类的关系,也可以替换成接口和实现类之间的关系。

 

为了更好理解里氏替换原则,举几个违反里氏替换原则的例子进行说明。

1、子类违反父类声明要实现的功能

父类中提供了sortOrderByAmount()订单排序函数,是按照订单金额来排序的,而子类重写了这个sortOrderByAmount()方法之后,是按照订单的创建日期来排序。那子类的设计违反了里氏替换原则。

 

2、子类违背父类对输入、输出、异常的约定

在父类中,某个函数约定:运行出错时返回null,获取不到数据的时候返回空集合(empty collection);而子类在重载函数之后,实现变了,运行出错,返回异常(exception),获取不到数据返回null,那么子类的设计违背了里氏替换原则。

在父类中,某个函数约定,输入的数据可以时任意整数;而子类重载之后,只允许输入正整数,负数就抛出,也就是说子类对输入数据的校验比父类更加严格了。那么子类的设计违背了里氏替换原则

在父类中,某个函数如果只会抛出ArgumentNullException,那么子类中只允许抛出ArgumentNullException异常,任何其他异常的抛出,都会导致违反里氏替换原则。

 

3、子类违背父类中所罗列的任何特殊书名

父类中定义了withdraw()提现函数的注释是这么写的:“用户的体现金额不得超过账户的余额……”,当子类重写withdraw()方法后,针对VIP账号实现了透支体现的功能,也就是提现金额大于账户余额,那子类的设计不符合里氏替换原则

 

上面三种情况时典型的违背了里氏替换原则,还有一个小窍门可判定子类设计是否违背里氏替换原则,那就是使用 父类的单元测试去验证子类的代码。某些单元测试运行失败,那就说明子类设计违反了里氏替换原则。

 

多态和里氏替换原则的区别?

多态和里氏替换原则所关注的角度不同,多态是面向编程的一大特性,也是面向编程语言的一种语法,它是一种代码的实现思路。

里氏替换原则是一种设计原则,是用来指导继承关系中子类该如何设计,才能在子类替换父类的时候,不改变原有程序的逻辑以及不破坏原有程序的正确性

 

参考:设计模式之美--王争

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值