为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,在设计开发程序的时候,需要遵循以下原则
开闭原则
- 对扩展开放,对修改关闭;
- 在需求变更的时候,在不修改软件实体的源代码或者是二进制代码的前提下,可以扩展模块的功能,使其满足新的需求;
- 可通过”抽象约束,封装变化”来实现开闭原则;
- 提高代码的可复用性;
-
里氏替换原则
继承必须确保超类所拥有的性质在子类中仍然成立;
- 子类可以扩展父类的功能,但是不能改变父类原有的功能;
- 反映了基类和子类之间的关系,是对开闭原则的补充,对实现抽象化的具体步骤的规范;
- 子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法,尽量不重写父类的方法;
- 子类可以有自己特有的方法;
- 当子类重载父类的方法时,方法的输入参数要比父类方法更宽松;
- 当子类实现父类的方法时,方法 输出/返回值需要比父类的方法更加精准;
- 比如鸟类定义了会飞的方法,但是鸵鸟虽然属于鸟类,但是不会飞,这就不能使得鸵鸟继承鸟类,如果继承则违背了里氏替换原则;
- 克服继承中重写父类造成的可复用性变差的缺点;
加强程序的健壮性,做到好的兼容性,提高程序的维护性/可扩展性;
依赖倒置原则
高层模块不应该依赖底层模块,两者都应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象;
- 面向接口编程,不要面向实现编程,通过面向接口编程来降低类之间的耦合性;
- 使用抽象类或者接口去定义规范和契约,而不去设计任何具体的操作,把展现细节的任务交给实现类去完成;
- 每个类尽量提供接口或抽象类,或者两者都具备;
- 变量的声明类型尽量是接口或者抽象类;
- 任何类都不应从具体类派生;
- 使用继承时尽量遵循里氏替换原则;
- 是实现开闭原则的重要途径之一,降低了客户与模块之间的耦合;
- 降低类之间的耦合;
- 减少并行开发引起的风险;
- 提高代码的可读性和可维护性;
-
单一职责原则
规定一个类应该有且仅有一个引起它变化的原因,否则这个类要拆分;
- 控制类的粒度大小,将对象进行解耦,提高其内聚性;
- 根据不同的职责,区分成不同的类,再把类分到不同的模块当中;
- 其中方法也适用单一职责原则,一个方法尽量处理好一件事情,有利于方法的重用;
- 降低类的复杂度;
- 提高类的可读性;
- 提高系统的可维护性;
变更引起的风险低,当修改一个功能的时候;可以显著降低对其他功能的影响;
接口隔离原则
为各个类建立他们需要的接口,而不是建立一个统一的接口去调用;
- 约束接口,针对抽象和程序整体框架的构建,降低类对接口的依赖性;
- 接口尽量小,一个接口只服务于一个子模块或者业务逻辑;
- 为依赖接口的类制定服务,只提供调用者需要的的方法,屏蔽不需要的方法;
- 根据不同的业务去划分接口;
- 提高内聚,减少对外交互,使用接口最少的方法去完成最多的事情;
- 减少项目工程的代码冗余;
- 提高系统的内聚性,减少对外交互,降低系统的耦合性;
- 提高系统的可维护性和灵活性;
-
迪米特法则
最少知识原则;
- 如果两个软件实体无需直接通信,那么就不应直接的相互调用,可以通过第三方转发该调用,降低类之间的耦合度,提高模块的相对独立性;
- 第三方同当前对象本身/当前对象的成员对象/当前对象所创建的对象存在关联/聚合或者组合关系,可以直接访问这些对象;
- 对于依赖者,只依赖于应该依赖的对象;对于被依赖者,只暴露应该暴露的方法;
- 在类的划分上应该创建弱耦合的类;
- 在类的结构上,尽量降低类成员的访问权限;
- 在类的设计上,优先考虑将一个类设置成不可变类;
- 在对其他类的引用上,将引用其他对象的次数降到最低;
- 不暴露类的属性成员,而是提供相应的访问器(get/set方法);
- 谨慎使用序列化功能;
- 降低类之间的耦合度,提高模块的相对独立性;
- 由于亲和度降低,提高类的可复用率和系统的扩展性;
-
合成复用原则
通过将已有对象纳入新对象中,作为新对象的成员对象来实现的新对象,对象可以调用已有对象的功能,从而达到复用;
- 要求软件复用时,要尽量先考虑组合或者聚合等关联关系来实现,其次再考虑使用继承关系实现;
- 如果使用继承必须遵守里氏替换原则,合成复用原则和里氏替换原则相辅相成,都是开闭原则的具体实现规范;
- 继承复用:通过继承父类来达到复用的效果,但是这将不利于类的扩展和维护,成为”白箱”复用;
- 合成复用:将已有的对象纳入新的对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能。成为”黑箱”复用,灵活性高;
- 维持了类的封装性;
- 新旧类之间的耦合度低;
- 复用灵活性高;
