1.“开——闭”原则:讲的是,一个软件应当对扩展开放,对修改关闭。即,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。换言之,应当可以在不必修改源代码的情况下改变这个模块的任务。
满足“开——闭”原则的设计可以个一个软件两个优越性:
1) 通过扩展已有的软件系统,可以提供新的行为,以满足对软件新的需求,使变化中的软件系统有一定的适应性和灵活性。
2) 已有的软件模块,特别是最重要的抽象层模块不能再修改,这就是使变化中的软件系统有一定的稳定性和延续性。
2.里氏代换原则:概念:一个软件实体如果使用的是一个基类的话,那么一定使用其子类,而且它根本不能察觉出基类对象和子类对象的区别。
里氏代换原则是继承复用的基石。只有当子类可以替换掉基类,软件的功能不会受到影响时,基类才能够在基类的基础上增加新的行为。
反过来的代换不成立。
必须指出,反过来的代换则不成立,即如果一个软件实例使用的是一个子类的话,那么它不一定使用基类。
3.接口隔离原则:概念:使用专门的接口比使用单一的接口好。从客户类的角度来讲,一个类对另一个类的依赖性应当是建立在最小接口上的。
“接口”理解为一个类所提供的所有方法的特征的集合,也就是一种逻辑上才存在的概念。
定制服务
接口隔离原则讲的是为同一个角色提供宽、窄不同的接口,以应对不同的客户端要求。
接口污染
过于臃肿的接口是对接口的污染。
4.合成/聚合复用原则:概念:在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。
另一种表述为:要尽量使用合成/聚合关系,尽量不要使用继承关系。
合成/聚合复用的好处
1) 新对象存取已有对象的唯一方法是通过已有对象的接口。
2) 这种复用是黑盒复用,因为已有对象内部细节是新对象所看不见的。
3) 这种复用所需的依赖较少。
4) 每一个新的类可以将焦点集中在一个任务上。
5) 这种复用可以在运行期间内动态进行,新对象可以动态地引用与已有对象类型相同的对象。
继承复用的缺点
1)破坏了包装,因为继承将超类的实现细节暴露给子类。由于超类的内部细节常常是对子类透明的,所以又称为白盒复用。
2)如果超类的实现发生改变,那么子类的实现也不得不发生改变。因此,当一个基类发生改变时,修改将扩散到每一级子类,设计师将做大量的修改。
3)从继承继承而来的实现是静态的,不可能在运行时间内发生改变,没有足够的灵活性。
5.依赖倒转原则:概念:要依赖于抽象,不要以来于具体。
另一种表述为:要针对接口编程,不要针对实现编程。
只要一个被引用的对象存在抽象类型,就应当在任何引用该对象的地方使用抽象类型,包括参量的类型声明,方法的返回类型的声明,属性变量的类型声明等。
怎样做到依赖倒转原则
以抽象方式耦合是依赖倒转原则的关键。由于一个抽象耦合关系总要涉及具体类从抽象类继承,并且需要保证在任何引用到基类的地方都可以替成其子类,因此,里氏代换原则是依赖倒转原则的基础。
在抽象层次上的耦合虽然有灵活性,但也带来了额外的复杂性。在某些情况下,如果一个具体类发生变化的可能性非常小,那么抽象耦合能发挥的好处便十分有限,这时使用具体耦合会更好。
6.迪米特法则:又叫做最少知识原则,就是说,一个对象应当对其他对象有尽可能少的了解。
迪米特法则的各种表述:
1) 只与你直接的朋友们通信
2) 不要跟“陌生人”说话
3) 每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
狭义的迪米特法则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
狭义迪米特法则的缺点
遵循狭义的迪米特法则会产生一个明显的缺点:会在系统里造成大量的小方法,散落在系统的各个角落,这些方法仅仅是传递间接的调用,因此与系统的商务逻辑无关。
朋友的确定
1) 当前对象本身(this)
2) 以参量形式传入到当前对象方法中的对象
3) 当前对象的实例变量直接引用的对象
4) 当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友
5) 当前对象所创建的对象
联系客服