这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战
- 里式替换原则(Liskov Substitution Principle LSP)
假如我们对接了不同的商城,每个商城,都有每个商城自己的下单逻辑,但是我们对外提供的下单逻辑只能有一套,所以需要封装一下,这里就遵守出了 里式替换原则。
在一般的 MVC 架构中,我们一般有 Controller、Service层。而 Service 层一般是接口和对应的实现类,类图如下
我们在下单的时候可以使用接口中的 submitOrder,具体的实现逻辑放在不同的子类里,比如我们可以有 JDSubmitOrderServiceImpl、 TMSubmitOrderServiceImpl 等。
里式替换原则:
1 | python复制代码If for each object o1 of type S there is an object o2 of type T such that for |
这是一种标准定义。还有一种通俗的定义:
1 | css复制代码Functions that use pointers or references to base classes must be able to |
再换句话说,就是 任何基类可以出现的地方,子类一定可以出现。
里式替换原则是在告诉我们,继承关系应该遵循哪些原则? 或者说,如果你要使用继承,那么你就应该遵守里式替换原则。
里氏替换原则主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中蕴含的原理。里氏替换原则是继承复用的基础,它反映了基类与子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。
里式替换原则有四层含义,或者说,当你实现继承的时候,应该遵守这四个规则。
- 子类必须完全实现父类的方法
如果子类不能够完全实现父类的方法,那么建议断绝继承关系,使用组合、依赖等代替继承关系。
比如我们的例子中,如果有一个类 XXXOrderServiceImpl 继承了 SubmitOrderService,但是没有实现 Service 中的接口,那么就应该断绝继承关系。
PS:其实这个原则应该没有说完,还有下句。子类必须完全实现父类的方法。但不得重写(覆盖)父类的非抽象(已实现)方法
就是说子类不能改变父类已经实现好的方法,不能改变父类方法的逻辑。
- 子类可以有自己的个性
或者说,子类可以有自己独有的方法、属性。但是这里需要注意:如果你在子类中定义了方法,那么你在使用这个类的时候就不能使用多肽了。
子类不仅可以继承父类中的方法和属性,还可以定义自己的方法和属性。但是这样做之后,就不能使用多肽了,比如,当我们在使用下单逻辑的时候,一般会这么定义:
1 | ini复制代码SubmitOrderService orderService = new JDSubmitOrderServiceImpl(); |
但是,如果我们在 JDSubmitOrderServiceImpl 中定义了一个自己的方法 xxxOrder(),如果想要使用该方法,就不能使用上面这种定义方式。
1 | ini复制代码JDSubmitOrderServiceImpl orderService = new JDSubmitOrderServiceImpl(); |
只能使用 JDSubmitOrderServiceImpl 作为对象的类型。
- 覆盖或实现父类的方法时输入参数(方法的参数)可以被放大
比如,我们在实现 SubmitOrderService 的时候,重写 submitOrder 方法的时候,可以将方法的参数定义成 Order 或者是 Order 的父类。
比如我们 SubmitOrderService 有个方法xxxOrder(ArrayList list)
参数是一个 ArrayList
,在实现这个方法的时候可以传入 ArrayList 的父类,可以这么定义xxxOrder(List list)
PS: 这里说的是参数可以被放大,是当你有不得不放大参数的时候,可以放大,而不是只要实现就去放大参数,一般在实现的时候尽量不要放大,而且,一般父类的方法参数都是某个类的父类,很少使用子类的,所以很少遇到放大参数的情况。
注意: 这里说的是方法定义的时候可以被放大。在实际调用的时候可以传入一个参数的子类。比如:
1 | ini复制代码SubmitOrderService orderService = new JDSubmitOrderServiceImpl(); |
这里我们传入的参数是 Order 的子类。而不是父类。
- 覆写或实现父类的方法时输出结果(方法的返回值)可以被缩小
跟第 3 条对应,这里说的是方法的返回值可以被缩小,比如父类方法的返回值是 List ,那么子类的返回值可以是 List 或者是 List 的子类。比如 ArrayList。
本文转载自: 掘金