面向对象的七大原则

单一职责原则

单一职责原则定义:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。

单一职责原则是实现高内聚、低耦合的指导方针。一个类承担的职责越多,它被复用的可能性越小。一个类的职责太重,将导致系统非常脆弱,一个职责的变化可能会影响到其他职责。另一方面,类的职责也不应过分细分,这将降低代码的维护性。

该职责的核心在于掌握好每个类的颗粒度大小。

开闭原则

开闭原则的定义:一个软件实体应当对扩展开放,对修改关闭。也就是说在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即实现在不修改源代码的情况下改变这个模块的行为。其中,软件实体可以是指一个软件模块、一个由多个类组成的局部结构或一个独立的类。

在面向对象的编程语言中,该原则一般是通过为系统定义一个相对稳定的抽象层(接口、抽象类)来体现的,具体类通过继承该抽象层来实现。在调用该软件实体时应该针对抽象层进行编程,实际所采用的具体类可通过配置文件进行配置(一般不把对配置文件的修改认为是对系统源代码的修改)。借助面向对象程序设计语言的多态机制,可以使程序按照预期进行。

符合开闭原则的软件,可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。百分之百的开闭原则很难达到,但是要尽可能使系统设计符合开闭原则。

里氏代换原则

里氏代换原则定义:所有引用基类(父类)的地方必须能透明地使用其子类的对象。

该原则目的在于指导面向对象程序设计语言中继承特性的使用。在面向对象的程序设计语言中,子类对象可以充当父类对象使用,子类与父类的关系是“is-a-kind-of”关系。里氏代换原则要求对软件设计者对父类和子类的具体定义有清晰的认识,例如:类Bird的定义是会飞的鸟,在使用类Bird时无需考虑其飞行速度为0的问题,此时类Ostrich(鸵鸟类)不应继承Bird类,因为这有可能会导致使用Bird类的程序发生除0异常等,该软件设计是违反里氏代换原则的。里氏代换原则要求软件中能使用基类的地方,替换成它的子类不会产生任何错误和异常。如果类Bird的定义仅仅是生物中的鸟,那么类Ostrich(鸵鸟类)可以继承Bird类,但使用类Bird的程序需要考虑鸟不会飞的可能性。

里氏代换原则要求我们要善用继承功能,父类和子类对外要符合里氏代换原则,而滥用继承功能会增加程序出错的可能性。

依赖倒转原则

依赖倒转原则:高层模块不应该依赖低层模块,它们都应该依赖抽象。即要 针对接口编程,不要针对实现编程。

在程序代码中传递参数时或在组合聚合关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口和抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。借助多态机制,程序会执行相应子类的方法。

里氏代换原则、依赖倒转原则是实现开闭原则基础。

 

依赖倒转原则中经常提到的两个概念——类之间的耦合和依赖注入。

类之间的耦合关系(依赖关系):

    零耦合关系:如果两个类之间没有任何耦合关系,称之为零耦合。

    具体耦合关系:具体发生在两个具体类(可实例化的类)之间,由一个类对另一个具体类实例的直接引用产生。

    抽象耦合关系:抽象耦合关系发生在一个具体类和一个抽象类之间,也可以发生在两个抽象类之间,使两个发生关系的类之间存有最大的灵活性。抽象耦合关系是依赖倒转原则的关键。

 

依赖注入:

    构造注入:通过构造函数注入另一个类的实例,实现聚合关系。

    设置注入:通过Setter方法注入另一个类的实例,实现聚合关系。

    接口注入:通过参数传递实例变量,该实例仅供该函数使用。

合成复用原则

合成复用原则定义:尽量使用对象组合,而不是继承来达到复用的目的。简言之:要尽量使用组合/聚合关系,少用继承。

继承为“白箱复用”,组合/聚合为“黑箱”复用,组合/聚合的耦合度相对较低,一个类的变化对其它类造成的影响相对较少,因此一般首选使用组合/聚合来实现复用;其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要谨慎使用继承复用。

接口隔离原则

接口隔离原则定义:一旦一个接口太大,则需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。

该原则可以理解为接口上的单一职责原则。接口应该尽量细化,每个接口中应只包含一个客户端(如子模块或业务逻辑类)所需的方法。

要注意接口的粒度大小,接口太小会导致接口泛滥,不利于维护;接口太大会违背接口隔离原则,灵活性较差,使用起来很不方便。

迪米特法则

迪米特法则(最少知识原则)定义:只与你的直接朋友通信,一个软件实体应当尽可能少与其他实体发生相互作用。

这样,当一个模块修改时,就会尽量少的影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。迪米特法则用于降低系统的耦合度,使类与类之间保持松散的耦合关系。

在迪米特法则中,对于一个对象,其朋友包括以下几类:

  1. 当前对象本身(this).

  2. 以参数形式传入到当前对象方法中的对象。

  3. 当前对象的成员对象。

  4. 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友。如,链表类中以头节点表示节点对象的集合。

  5. 当前对象内部直接创建的对象。

  6. 当前对象可访问的全局对象。

狭义的迪米特法则中,对象应该只与上述六类对象通信,如下图。如果对象A需要与对象C通信,那么对象A应该通过对象B去转发,而不应该在对象A内部获取对象C去通信。特别是,对象应该避免调用另一个方法返回的成员对象的方法。对于许多使用点作为字段标识符的现代面向对象语言,法则可简单地表述为“仅使用一个点”。也就是说,代码a.b.Method()违反迪米特法则。作为类比,当一个人想要一只狗走路时,他不应该指挥狗的腿直接行走; 相反,应该先命令狗,然后狗命令自己的腿去行走。

狭义的迪米特法则虽然降低了类之间的耦合,但是会在系统中增加大量的小方法并散布在系统的各个角落,这会使得系统的不同模块之间的通信效率降低。

 

面向对象的七大原则_第1张图片

 

 

广义的迪米特法则就是指对象之间的信息流量、流向以及信息的影响控制,主要是对信息隐藏的控制。主要体现在以下几点:

  1. 在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及。
  2. 在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限。
  3. 在类的设计上,只要有可能,一个类型应当设计成不变类。
  4. 在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

 

你可能感兴趣的:(经验总结)