类A
访问 类B
,耦合度由高到低依次为:
名称 | 概述 |
---|---|
隐式访问(需要避免) | B 既没有在 A 的规格中出现,也没有在实现中出现。即 a.methodA.methodB() 这种访问方式,这种方式也是典型的违反迪米特法则的标志。 |
在实现中访问(可接受且是必要的) | B 的引用是 A 方法中的局部变量。即在类 A 中的一个方法内部临时请求并保持对 B 的引用,而 类B 没有出现在 类 A 的规格(接口参数和返回值)中。 |
成员变量访问(提倡) | B 的引用是 A 的成员变量。直接在类 A 中声明了 B 类型的变量,即 B 是 A 的成员变量/全局变量,B 是 A 规格的一部分。 |
参数变量访问(提倡) | B 的引用是 A 的方法的参数变量。类 A 中的方法头部把 B 作为参数传入,即表明在 A 方法内部可以访问 类 B ,比成员变量访问的范围更窄(仅在类内部可访问),耦合性也更弱,所以更好 |
无访问(理论最优) | 无关联耦合,维护时不需要对方任何信息,完全独立。 |
要针对接口编程,而不是针对实现编程。
客户端不应该依赖那些它不需要的接口。使用多个专门的接口来取代一个统一的接口。
又称最少知识原则。一个类只与它直接的朋友交流,只引用它直接的朋友的方法。不要出现 a.b.Method()
这类场景。
子类继承父类,子类与父类间的继承耦合由高到低依次为:
名称 |
---|
修改规格、修改实现、精化规格(不可接受) |
精化实现(可接受) |
扩展(最好的) |
无耦合(两个类没有继承关系了) |
即要求子类在继承父类的时候,要保持父类的方法接口不变,保持父类方法的实现语义不变,这也就是里氏替换原则的要求。
子类型必须能够替换掉基类型而起同样的作用。要求:
子类可以扩展父类功能,但不能改变父类原有功能。这样才可以保证在软件系统中,一个可以接受父类对象的地方必然可以接受一个子类对象(反过来不一定成立)。
只为了复用而不为了组织类型差异的继承用法往往是不符合 LSP 的,应使用组合代替继承实现复用。
信息联合起来能够支撑行为的执行,行为完成对这些信息的操纵。面向对象思想中,应该是把类的信息和访问这些信息的行为放在一个类中。
一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中;就一类而言,应该仅有一个引起它变化的原因。
即控制类的粒度大小,降低类的复杂度,提高可维护性,降低变更风险。
好的设计应该对 扩展
开放,对 修改
关闭。抽象化是开闭原则的关键。
抽象不应该依赖于细节,细节应该依赖于抽象;高层模块不应该依赖于低层模块,它们都应该依赖于抽象。
要针对抽象编程,不要针对具体类编程。