好久没写文章了,这里整理下以前看过的一些软件设计原则的资料吧,让我们一起看看吧。
开闭原则
概念: Open-Closed Principle, OCP, 一个软件实体如类,模块,函数应该对扩展开放,对修改关闭, 强调用抽象构建框架,用实现扩展细节,提高软件系统的可复用性和可维护性。
理解:
- 开闭原则可以应用在不同粒度的代码中,可以是模块,可以是类,还可以是方法。 同一个代码改动,在粗粒度上是修改,但在细粒度上是扩展。所以没必要纠结是修改还是扩展,判定代码改动的合格标准应该是没有破坏原来代码的运行,没有破坏原有的单元测试。
- 在编写代码时,思考代码可能变更点,事先留好扩展点, 封装可变部分,隔绝变化,提供抽象的不可变接口。
- 开闭原则并不是万能的。我们需要注意代码的扩展性和可读性的平衡。
依赖倒置原则
概念: Dependence Inversion principle, DIP。设计代码结构时,高层模块不应依赖于底层模块, 二者都应该依赖于抽象。抽象不应该依赖细节,细节应该依赖于抽象。通过依赖倒置,减少类与类之间的耦合性,提高系统的稳定性, 提高代码的可读性和可维护性,降低修改程序的风险。
补充:
-
控制反转(IOC)
这里说的不是Spring IOC,而是一种设计思想。核心是框架提供了一个可扩展的代码骨架,用来组装对象,管理整个执行流程。在利用框架开发的时候,只需要往预留的扩展点,添加与业务有关的代码,就利用框架来驱动整个程序流程的执行。流程控制权由程序员"反转"到框架。
控制反转的实现方法很多,比如模板设计模式, 依赖注入等。
依赖注入框架很多,比如Spring, Google Guice等。
理解:
- 以Tomcat为例,Tomcat是高层模块,Web应用程序代码是低层模块,Tomcat和Web应用程序没有直接的依赖关系,两者都依赖Servlet规范。
单一职责原则
概念: Simple Responsibility Principle, SRP。不要存在多于一个导致类变更的原因。也就是不要涉及大而全的类,要设计粒度小,功能单一的类。
理解:
- 如何判断一个类的职责是否单一?
- 类中的代码行数,函数或属性过多
- 类依赖的其他类过多
- 私有方法太多
- 类名比较难起
- 大量的方法集中操作类中的某几个属性
- 单一职责原则不是银弹, 避免拆分的过细,导致降低内聚性,影响可维护性。
接口隔离原则
概念: Interface Segregation Principle, ISP。使用多个专门的接口,客户端不应该依赖它不需要的接口。
理解:
- 和单一职责原则的区别:
- 单一职责职责针对的是模块,类,接口的设计
- 接口隔离原则提供了一种判定接口是否职责单一的标准: 通过调用者如何使用接口来间接判定,如果调用者只使用了部分接口或接口的部分功能,那接口的设计不够职责单一。
- 接口设计要尽量单一,尽量细粒度。
迪米特法则
概念: Law of Demeter, LOD。又叫最小知道原则(Least Knowledge Priciple, LKP)。尽量降低类与类的耦合,迪米特法则主要强调只和朋友交流,不和陌生人说话,出现在成员变量,方法输入/输出参数中的类可以称为成员朋友类,出现在方法体内部的类不属于朋友类。
理解:
- 主要强调的是高内聚,松耦合。高内聚指导类的设计,松耦合指导类与类之间依赖关系的设计。
- 不该有直接依赖关系的类之间不要有依赖。有依赖关系的类之间,尽量只依赖必要的接口。
里氏替换原则
概念: 子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。约束继承泛滥,加强程序的健壮性, 兼容性,维护性和扩展性。
理解:
- 子类可以实现父类的抽象方法,不能覆盖父类的非抽象方法。也就是违背父类声明要实现的功能
- 子类不能违背父类对于输入,输出,异常的约定
- 里氏替换原则是用来指导,继承关系中子类该如何设计的原则。子类的设计要保证在替换父类时,不改变原有程序的逻辑,不破坏原有程序的正确性。
合成复用原则
概念: Composite/Aggregate Reuse Principle, CARP。尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的,可以使系统更灵活, 降低类与类之间的耦合。
理解:
- 维持类的封装性,合成复用又称为"黑箱"复用。
- 合成复用耦合性低
- 灵活性高,复用可以在运行时动态进行。
其他原则
除了七种经典的软件设计原则,还有KISS,YAGNI,DRY原则。
- KISS: 尽量保持简单
- 不过度优化
- 不重复造轮子
- 不使用复杂的技术解决简单问题
- YAGNI: 不做过度设计
- 不提前编写代码,预留好扩展点
- 不提前引入不需要的开发包
- DRY: 不重复代码
- 实现逻辑重复,但功能语义不重复的代码,并不违反 DRY 原则。实现逻辑不重复,但功能语义重复的代码,也算是违反 DRY 原则。除此之外,代码执行重复也算是违反 DRY 原则
- 代码复用性方法:
- 减少代码耦合
- 满足单一职责原则
- 模块化业务与非业务逻辑分离
- 通用代码下沉
- 继承、多态、抽象、封装应用模板等设计模式