-
单一职责原则(Single Responsibility Principle,SRP)
定义:There should never be more than one reason for a class to change.即有且只有一个原因引起类的变更。即类要提供的功能尽可能简单明确。
其意义如下:
- 降低类的复杂性,实现的职责具有清晰的定义
- 提高可读性
- 提高可维护性
- 降低变更引起的风险,对系统扩展性和可维护性都有帮助。
但是单一职责存在的一个问题是,“职责”没有一个明确的划分标准。如果分的太细,则会导致接口和实现类的数量的增加,反而提高了负责度,降低了可维护性。
在具体应用时要适度把握。
-
接口隔离原则(Interface Segregation Principle,ISP)
有两种定义
第一种:Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该强行依赖它不需要的接口)
第二种:The dependency of one class to another one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)
接口隔离原则与单一职责原则有些相似,不过不同在于:单一职责原则要求的是类和接口职责单一,注重的是职责,是业务逻辑上的划分。而接口隔离原则要求的是接口的方法尽量少,尽量有用(针对一个模块)
-
开闭原则(Open Closed Principle,OSP)
开闭原则的核心是:对扩展开放,对修改关闭
http://developer.51cto.com/art/201203/323600.htm
-
依赖倒转原则(Dependence Inversion Principle,DIP)
定义:High level modules should depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.
即:
- 高层模块不应该依赖低层模块,两者都应该依赖于抽象(抽象类或接口)
- 抽象(抽象类或接口)不应该依赖于细节(具体实现类)
- 细节(具体实现类)应该依赖抽象
抽象:即抽象类或接口,两者是不能够实例化的。
细节:即具体的实现类,实现接口或者继承抽象类所产生的类,两者可以通过关键字new直接被实例化。
而依赖倒置原则的本质其实就是通过抽象(抽象类或接口)使各个类或模块的实现彼此独立,不相互影响,实现模块间的松耦合。但是这个原则也是6个设计原则中最难以实现的了,如果没有实现这个原则,那么也就意味着开闭原则(对扩展开发,对修改关闭)也无法实现。
依赖倒置有三种方式来实现
1、通过构造函数传递依赖对象
比如在构造函数中的需要传递的参数是抽象类或接口的方式实现。
2、通过setter方法传递依赖对象
即在我们设置的setXXX方法中的参数为抽象类或接口,来实现传递依赖对象
3、接口声明实现依赖对象
http://developer.51cto.com/art/201203/322199.htm
-
里氏代换原则(Liskov Substitution Principle,LSP)
定义:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
也就是说,所有使用基类的地方,都可以使用其子类。也是一个良好的继承规范。
-
迪米特原则(Law of Demeter,LOD 或者Least Knowledge Principle,LKP)
定义:一个对象应该对其他对象了解最少
迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用性才可以提高。
http://developer.51cto.com/art/201203/323155.htm
-
合成聚合原则(Composite/Aggregate Reuse Principle,CARP)
合成聚合原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。
简而言之:要尽量使用使用合成/聚合,尽量不要使用继承。
合成表示一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样,打个比方:人有两个胳膊,胳膊和人就是部分和整体的关系,人去世了,那么胳膊也就没用了,也就是说胳膊和人的生命周期是相同的
. 合成关系用实心的菱形+实线来表示
. 聚合表示一种弱的拥有关系,体现的是A对象可以包含B对象,但是B对象并不是A对象的一部分,打个比方:人是群居动物,所以每个人属于一个人群,一个人群可以有多个人,所以人群和人是聚合的关系
. 聚合关系用空心的菱形+实线来表示
- 为什么尽量不要使用类继承而使用合成/聚合?
. 对象的继承关系在编译时就定义好了,所以无法在运行时改变从父类继承的子类的实现
. 子类的实现和它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化
. 当你复用子类的时候,如果继承下来的实现不适合解决新的问题,则父类必须重写或者被其它更适合的类所替换
这种依赖关系限制了灵活性,并最终限制了复用性