子类型必须能够替换掉它们的基类型。
就是说一个参数是基类类型参数的函数,再函数掉用的时候,传入一个派生类的参数,这时候函数的功能是正常的。这样才被能满足LSP原则。
违反LSP原则的提示,都是以某种方式从其基类中去除功能的派生类有关,完成功能少于基类的派生类通常是不能替换其基类的,因此就违反的了LSP。
另一种LSP的违反形式是在派生类的方法中添加了其基类不会抛出的异常。如果基类使用者不期望这些异常,那么把他们添加到派生类的方法中就会导致不可替代性,此时如果要遵循LSP原则,就必须改变使用者的期望,要么派生类就不应该抛出这些异常。
a. 高层模块不因该依赖于底层模块,二者都应该依赖于抽象。 b. 抽象不应该依赖于细节,细节应该依赖于抽象。
层次化
所有结构良好的面向对象架构都具有清晰的层次定义,每层次通过一个良好的,受控的接口向外提供了一组内聚的服务。
倒置的接口所有权
著名的Hollywood原则:”Don’t call us, we’ll call you.” 底层模块实现高层模块声明并被高层模块调用的接口。
依赖于抽象
程序中所有的依赖关系都应该终止于抽象类或者接口。
不应该强迫用户依赖于它们不适用的方法。
接口易被污染,我们就需要接口分离。接口被不同的客户使用,客户程序是分离的,所以接口也应该是分离的。因为客户程序对他们使用的接口施加又压力。
类接口与对象接口,客户不是必须通过该对象的接口去访问它,也可以通过委托或者通过该对象的基类去访问它。
胖类(fat class)会导致他们的客户程序之间产生不正常的并且有害的耦合关系。当一个客户程序要求 胖类进行一个改动的时候,会影响到所有其他的客户程序。因此客户程序因该仅仅依赖于他们实际调用的接口。 通过把胖类的接口分解为多个特定客户程序的接口,可以实现这个目标。每个特定于客户程序的接口仅仅声明它的特定客户或者客户组调用的那些接口函数。接着该胖类就可以继承所有特定于客户程序的接口,并实现他们。这就解除了客户程序和他们没有调用方法的依赖关系,并使客户程序之间互不依赖。