在应用开发过程中,最难的不是完成应用的开发工作,而是在后续的升级、维护过程中让应用系统能够拥抱变化。拥抱变化也就意味着在满足需求且不破坏系统稳定性的前提下保持高可扩展性、高内聚、低耦合,在经历了各版本的变更之后依然保持清晰、灵活、稳定的系统架构。为此,我们需要了解并遵循面向对象六大原则。
一、单一职责原则
SRP (Single Responsibility Principle)
定义:就一个类而言,应该仅有一个引起它变化的原因。
理解和使用建议:简单的来说,一个类中应该是一组相关性很高的函数、数据的封装。如何划分一个类、一个函数的职责,每个人都有自己的看法,这需要根据个人经验、具体的业务逻辑而定。但是,它也有一些基本的指导原则,例如,两个完全不一样的功能就不应该放在同一个类中。一个类中应该是一组相关性很高的函数、数据的封装。
二、开闭原则
OCP (Open Close Principle)
定义:软件中的对象(类、模块、函数等)应该对于扩展是开放的,但是对于修改是封闭的。
理解和使用建议:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会将错误引入原本已经经过测试的旧代码中,破坏原有系统。因此,当软件需要变化时,我们应该尽量通过扩展的方式来实现变化,而不是通过修改已有的代码来实现。当然,在现实开发中也没有那么理想化的状况,完全地不用修改原来的代码,因此,在开发过程中需要自己结合具体情况进行考量,是通过修改旧代码还是通过继承使得软件系统更加稳定,更加灵活,适当的时候也要修改旧代码以更方便实现扩展。
三、里氏替换原则
SLP (Liskov Substitution Principle)
定义:所有引用基类的地方必须能够透明地使用其子类的对象。
理解:只要父类能出现的地方子类就可以出现,并且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。可以说里氏替换原则的核心原理是抽象,抽象又依赖于继承这个特性。
使用建议:建立抽象,通过抽象建立规范,具体的实现在运行时替换掉抽象,保证系统的扩展性、灵活性。
四、依赖倒置原则
DIP (Dependence Inversion Principle)
定义:指代一种特定的解耦形式,使得高层次的模块不依赖于低层次模块的实现细节的目的,依赖模块被颠倒了。
有以下几个关键点:
(1)高层模块不应该依赖低层模块,两者都应该依赖其抽象。
(2)抽象不应该依赖细节。
(3)细节应该依赖抽象。
理解:在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或继承抽象类而产生的类就是细节。
高层模块就是调用端,低层模块就是具体实现类。所以依赖倒置原则在Java语言中的表现就是:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类发生的。简单的说就是要做到“面向接口编程”,这也是面向对象的精髓之一。
使用建议:如果类与类直接依赖于细节,那么它们之间就有直接的耦合,当具体实现需要变化时,意味着要同时修改依赖者的代码,这限制了系统的可扩展性,这时候只需要抽象低层次模块的类即可。常见用法有工厂方法模式。
五、接口隔离原则
ISP(Interface Segregation Principles)
定义:客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。
理解和使用建议:接口隔离原则将非常庞大、臃肿的接口拆分成更小的和更具体的接口,这样客户将会只需要知道他们感兴趣的方法。接口隔离原则的目的是系统解开耦合,从而容易重构、更改和重新部署。
六、迪米特原则
LOD(Law of Demeter)
定义:一个对象应该对其他对象有最少的了解。
理解和使用建议:一个类应该对自己需要耦合或调用的类知道得最少,类的内部如何实现和调用者或者依赖者没关系,调用者或者依赖者只需要知道它所需要的方法即可,其他的可一概不用管。类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。