设计模式02:面向对象设计原则
对于面向对象的软件系统设计来说,在支持可维护性的同时,提高系统的可复用性是一个核心的问题,面向对象设计原则正是为解决这个问题而诞生的。
1.面向对象设计原则
常用的面向对象设计原则包括以下7个:
单一职责原则(SRP):类的职责要单一,不能将太多的职责放在一个类中。
开闭原则(OCP):软件实体对扩展是开放的,但对修改是关闭的,即在不修改一个软件实体的基础上去扩展其功能。
里氏代换原则(LSP):在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类对象。
依赖倒转原则(DIP):要针对抽象层编程,而不要针对具体类编程。
接口隔离原则(ISP):使用多个专门的接口来取代一个统一的接口。
合成复用原则(CRP):在系统中应该尽量多使用组合和聚合关联关系,尽量少使用甚至不使用继承关系。
迪米特法则(LoD):一个软件实体对其他实体的引用越少越好,或者说如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互。
2.单一职责原则
单一职责原则是指,一个对象应该只包含单一的职责,而且该职责被完整地封装在一个类中。
单一职责原则用于控制类的粒度大小。
单一职责原则是实现高内聚、低耦合的指导方针。
3.开闭原则
开闭原则是指,一个软件实体应当对扩展开放,对修改关闭。也就是说,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即实现在不修改源代码的情况下改变这个模块的行为。
为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。
开闭原则是实现面向对象的可复用设计的基石。
4.里氏代换原则
里氏代换原则是指,所用引用基类(父类)的地方必须能透明地使用其子类的对象。可以通俗的理解为:在软件中如果能够使用基类对象,那么一定能够使用其子类对象。把基类都替换成它的子类,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类的话,那么它不一定能够使用基类。
使用里氏代换原则需要注意以下几个问题:
(1)子类的所有方法必须在父类中声明,或子类必须实现父类中声明的所有方法。
(2)在运用里氏代换原则时,尽量把父类设计为抽象类或接口。
里氏代换原则是开闭原则的具体实现手段之一。
5.依赖倒转原则
依赖倒转原则是指,代码要依赖于抽象的类,而不要依赖于具体的类;要针对接口或者抽象编程,而不是针对具体类编程。
依赖倒转原则是实现面向对象设计的主要机制。
依赖倒转的常用实现方式之一是在代码中使用抽象类,而将具体类放在配置文件中。
5.1类之间的耦合
在面向对象系统中,两个类之间通常可以发生三种不同的耦合关系:
(1)零耦合关系:两个类之间没有任何的耦合关系。
(2)具体耦合关系:具体耦合关系发生在两个具体类(可实例化的类)之间,由一个类对另一个具体类实例的直接引用产生。
(3)抽象耦合关系:抽象耦合关系发生在一个具体类和一个抽象类之间,也可以发生在两个抽象类之间,使两个发生关系的类之间存在最大的灵活性。
以抽象方式耦合是依赖倒转原则的关键。
里氏代换原则是依赖倒转原则的基础。
5.2依赖注入
依赖注入就是将一个类的对象传入另一个类,注入时应该尽量注入父类对象,而在程序运行时再通过子类对象来覆盖父类对象。
依赖注入分为:构造注入、设值注入、接口注入。
6.接口隔离原则
接口隔离原则是指,一旦一个接口太大,则需要将它分割成一些更细小的接口,使用该接口的客户端仅需要知道与之相关的方法即可。
7.合成复用原则
合成复用原则是指,尽量使用对象组合,而不是继承来达到复用的目的。
在面向对象设计中,通过组合/聚合关系或通过继承都可以实现复用已有的设计,这两种复用机制的特点如下:
(1)通过继承来进行复用,实现简单,易于扩展,但是继承复用会破坏系统的封装性。这种复用是透明的,又称为“白箱复用”。
(2)通过组合/聚合的方式进行复用,可以使得成员对象的内部实现细节对于新对象是不可见的,所以又称为“黑箱复用”。相对继承复用而言,其耦合度相对较低,成员的变化对新对象的影响不大。
8.迪米特法则
迪米特法则是指,一个软件实体应当尽可能少的与其他实体发生相互作用。
在迪米特法则中,对于一个对象,其朋友包括以下几类:
(1)当前对象本身。
(2)以参数形式传入到当前对象方法中的对象。
(3)当前对象的成员对象。
(4)如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友。
(5)当前对象所创建的对象。
迪米特法则的主要用途在于控制信息的过载。
在运用迪米特法则时,需要注意以下几点:
(1)在类的划分上,应当尽量创建松耦合的类,类之间的耦合越低,就越有利于复用。
(2)在类的结构设计上,每一个类都应当尽量降低其成员变量的和成员函数的访问权限。
(3)在类的设计上,只要有可能,一个类型应当设计成不变类。
(4)在对其他类的引用上,一个对象对其他对象的引用应当降到最低。
备注:本博文根据刘伟主编的《设计模式》第二章总结而得。