设计模式之美——里式替换原则 和 接口隔离原则

Posted iblade

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之美——里式替换原则 和 接口隔离原则相关的知识,希望对你有一定的参考价值。

里式替换原则

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

多态的目的: 让父类或接口根据引用的子类或实现的不同, 呈现出不同的功能形态; 里氏代换原则的目的: 对于多态中呈现出来的功能形态, 加了约束(不能违背父类功能的大方向).

实际上,里式替换原则还有另外一个更加能落地、更有指导意义的描述,那就是“Design By Contract”,中文翻译就是“按照协议来设计”。

进一步解释:子类在设计的时候,要遵守父类的行为约定(或者叫协议)。父类定义了函数的行为约定,那子类可以改变函数的内部实现逻辑,但不能改变函数原有的行为约定。这里的行为约定包括:函数声明要实现的功能;对输入、输出、异常的约定;甚至包括注释中所罗列的任何特殊说明。实际上,定义中父类和子类之间的关系,也可以替换成接口和实现类之间的关系。

哪些代码明显违背了 LSP?

接口隔离原则

“Clients should not be forced to depend upon interfaces that they do not use。”
客户端不应该被强迫依赖它不需要的接口。其中的“客户端”,可以理解为接口的调用者或者使用者。

接口的三种理解:

  • 一组 API 接口集合
  • 单个 API 接口或函数
  • OOP 中的接口概念(interface)

接口隔离原则跟单一职责原则有点类似,不过稍微还是有点区别。单一职责原则针对的是模块、类、接口的设计。而接口隔离原则相对于单一职责原则,一方面它更侧重于接口的设计,另一方面它的思考的角度不同。它提供了一种判断接口是否职责单一的标准:通过调用者如何使用接口来间接地判定。如果调用者只使用部分接口或接口的部分功能,那接口的设计就不够职责单一。


课堂讨论:

老师此题大有深意,我们可以从此思考题中方法的设计来深化对单一职责和接口隔离的理解:
接口隔离,强调的是调用方,是否只使用了接口中的部分功能?若是,则违反接口隔离,应当细粒度拆分接口,从这个例子看,调用方诉求与方法名完全一致,通过方法内部封装两个操作,实现原子性,达成了调用方的最终目的,不多不少。

单一职责,不强调是否为调用方,只要能某一角度观察出,一个模块/类/方法,负责了多于一件事情,就可判定其破坏了单一职责,基于此经典理论,不假以深层次思考的角度出发,从方法本身的命名(做两件事)就可断定,它一定是破坏了单一职责的,应该拆分为两个操作。

但我们可以结合老师说的,判定职责是否单一,要懂得结合业务场景,业务需求,此方法,其实就是要通过JDK提供的CAS乐观自选锁(方法最终依赖硬件指令集原语,Compare And Swap)从“原语”这一词的含义看,其实也是同时、原子性地做了一件“完整”的事情,因此,考虑这一点,是可以判定它符合单一职责的。

而这其实正是单一职责判定结果,往往见仁见智的原因:基于不同的角度,不同的立场,不同的业务理解,往往可以得到不同的判定结果,但不必纠结,判定过程中用到的思想才是精髓。

以上是关于设计模式之美——里式替换原则 和 接口隔离原则的主要内容,如果未能解决你的问题,请参考以下文章

设计模式—— 七大设计原则

设计原则之里式替换原则

设计原则之SOLID 原则

设计模式——面向对象设计原则

前端需要掌握的设计模式

前端需要掌握的常见设计模式