SOLID五大原则
面向对象编程有五大原则:
- Single responsibility principle:单一职责原则,一个对象应该具有单一功能,不应该将过多的功能赋予一个类
- Open-close principle:开闭原则,对扩展开发,对修改关闭。
- Liskov substitution principle:里氏替换原则,程序里的对象可以被其子类替换,且不改变其正确性。
- Interface segregation principle:接口隔离原则,多个客户端特定接口比一个用途广泛的接口好
- Dependency inversion principle:依赖反转原则,依赖于抽象而不是一个实例
开发软件的目的,是实现软件的功能,随后,是提高软件的性能,容错性,可扩展性,可维护性,稳定性等。在软件设计之初,软件的功能性是首要考虑目标;对尽可能多的错误输入进行有效的反馈可以提高软件的容错性;对流程逻辑进行和里的设计和对java语言进行合理的使用,可以提高软件的性能;而遵循SOLID原则进行设计,可以有效的增加程序的可维护性和扩展性,而所有的其他特性决定了软件的稳定性。
单一职责原则是设计类的时候,使其具有单一功能,比如说,person类只具有人的功能,它不能再具有人之外的其他功能,如果你想设计一个超人,请增加一个类,super-person。
开闭原则,对扩展开发,对修改关闭。在软件的生命周期内,因变化,升级,和维护等原因需要对软件进行修改的时候,尽量通过扩展实体,而不是通过修改已有代码来实现变化。
里氏替换原则,程序的对象可以被子类的对象替换,且不会改变程序的正确性。子类可以无缝替换父类,这在编程语言特性上已经实现,可是不改变程序的正确性,需要开发人员对子类进行良好的设计。
接口隔离原则,为每一个实现类设计一个特定接口,好过讲所有实现类的功能设计为一个接口。这个和类的单一职责类时,是对接口的的单一职责的规定。
依赖反转原则:是指一种特定的解耦(传统的依赖关系创建在高层次上,而具体的策略设置则应用在低层次的模块上)形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。
我们开发模块的接口和实现类是相互影响的,如果我们需要改变接口,那么实现类势必受到影响,如果我们提供的接口不满足实现类的需求,就需要我们改变接口来满足实现类新的需求。如果我们提供的接口过于肥胖,即抽离所有暴露的方法封装在一个接口中,就会导致:1、实现类可能会需要实现不需要的方法,加重负担;2、接口一旦改变,无论改变涉及不涉及实现类使用的接口,都需要实现类进行改变。
所以我们需要把肥胖的接口按照不同角色(即功能)分割开来,形成不同的角色接口,不同的客户都使用不同的角色,那么我们在改变接口的时候,只需要对应的实现类改变即可。
Robert C. Martin说单一职责的是指每一个module或则class都只有一个改变的原因,而这个改变的原因一定是人提出的,所以这个原则是和人有关的。
单一职责原则要求class或module只有一个职责,而将单个多角色接口(肥胖的接口)分离成多个单角色接口,这样我们对应的实现类就可以更明确自己的责任,减少改变的原因,实现单一职责原则,
开闭原则是对修改关闭,对扩展开放。这其中的关键是抽象和多态。当依赖于抽象的时候,我们就一个随时更好具体的实现类来实现变化。
个人理解,他真正的指的是在增加一个功能的时候,只需要增加新功能代码,不需要修改使用这些功能的代码。但是在现实中,是不可能100%对修改关闭的,所以我们需要根据经验去,将哪些需要不得不修改的地方独立出去,在修改的时候尽量降低影响。
里氏替换原则是子类可以替换父类,且破坏程序的正确性。这个规则强调了子类和父类要在外在行为,即公共方法上保持一直。如何保证父子类在行为上保持一致?我们声明方法的时候,需要声明前置条件和后置条件,要想保持父子类行为一致,就需要子类的前置条件要比父类的前置条件宽松,以使父类的前置条件完全可以使用子类,子类的后置条件要比父类严格,以使子类的后置条件完全使用于父类。
依赖倒置原则是
- 高层次模块不应该依赖低层次模块,他们都应该依赖抽象;
- 抽象不应该依赖细节,细节应该依赖抽象
这里为什么要用倒置呢?看下图:
这是原本的依赖关系
这是倒转之后的依赖关系:
看箭头!看箭头!看箭头!反向是不是倒转了。接口属于高层定义的,那么低层模块就相当于依赖于高层了,这是我理解的倒转。
高内聚,低耦合时每个程序员追求的目标,而要想实现这些目标,就需要一些规则支撑,SOLID就是这样的规则。而理解了这些规则,可以更好的理解涉及模式。