概念基础
经典定义
模式起源于建筑业而非软件业,下面是最早研究模式的 Christopher Alexander 博士对模式下的定义:
A pattern is a successful or efficient solution to a recurring problem within a content.
模式是在特定环境下人们解决某类重复出现问题的一套成功或有效的解决方案。
在软件业当中,最经典的设计模式研究人员莫过于“四人组”(GoF),他们对设计模式的定义如下:
Design patterns are descriptions of comminicating objects and classes that are customized to solve a general design problem in a particular context.
设计模式是在特定环境下为解决某一通用软件设计问题提供的一套定制的解决方案,该方案描述了对象和类之间的相互作用。
设计模式结构
设计模式是和数据结构与算法同层次的知识点,利用数据结构与算法可以写出高效的代码,利用设计模式可以写出可扩展、可读、可维护的高质量代码。
在软件业当中,设计模式也可以看作是软件模式中的一部分,负责优化编码、实现高质量代码的一部分。
设计模式和软件模式类似,基本结构主要由 4 个部分构成:
- 模式名称:简易描述模式的问题呈现、解决方案或实现效果
- 问题呈现:描述何时使用模式,包含了设计中存在的问题以及问题存在的原因
- 解决方案:描述组成成分以及这些组成成分之间的相互关系、各自的职责和协作方式
- 实现效果:应用模式之后的效果以及在使用模式时应权衡的问题
目的和优点
掌握设计模式之后,在以下场景的作用非常大:
- 使用设计模式作为编码标准,能方便开发过程中的沟通和交流
- 面对复杂代码、功能、系统的设计和开发,也能够得心应手、游刃有余
- 利用设计模式编写好的代码,可以在团队中脱颖而出,告别被别人吐槽代码写得烂
- 优秀的开源项目会使用很多设计原则、设计模式或设计思想,熟悉这些可以在阅读代码时更轻松
- 面试时会有问设计模式的情况,掌握设计模式可以轻松应对
- 职业发展到更高级的工程师,代码的质量影响着日常开发,作为面试官也需要了解
评价编码质量
学习设计模式就是为了提高代码的质量,在学习设计模式之前,应当先了解编码质量的概念和评价标准。
代码质量是一个综合各种标准得到的结论,不能通过单一的维度去评价一段代码写得好坏。即使是可扩展性非常好的代码,但是可读性非常差,并不能评价这段代码质量高。
如何评价
对编码质量的常见评价标准非常多,而它们又存在着包含、重叠、相互影响的关系,如一段代码的可读性、可扩展性非常好,也意味着这段代码的可维护性非常好。
在日常开发中,通常是无法客观地去评价代码的质量高低,对于同一段代码,高级开发工程师可能觉得可读性非常好,而初级开发工程师就会觉得难以阅读,他们的评价标准肯定是不一样的。
评价标准
代码质量的评价词语非常多,但使用时应尽量避免过于抽象或过于细节的评价,尽量使用较为精准的词语。
如下是常用的几个评价标准:
- 可维护性(maintainability):指的是可以在不破坏原有设计、不引入新 bug 的前提下快速修改或者添加代码
- 可读性(readability):通过看代码是否符合编码规范、命名是否达意、注释是否详尽、模块划分是否清晰、是否符合高内聚低耦合等等
- 可扩展性(extensibility):指的是在不修改或少量修改原有代码的前提下,通过扩展的方式添加新的功能代码
- 简洁性(simplicity):代码要尽量简单,逻辑清晰,这样可以使得代码易读、易维护
- 可复用性(reusability):尽量减少重复代码的编写,复用已有的代码,解耦、高内聚、模块化都能提高代码的可复用性
- 可测试性(testability):代码可测试性的好坏,能从侧面上非常准确地反映代码质量的好坏
其中可维护性、可读性、可扩展性是最重要的三个评价标准。
内聚、耦合
内聚指的是一个模块内部各成分之间相关联程度的度量。所谓高内聚,就是相近的功能应该放在一个模块内,不相近的功能不要放在一个模块内。
耦合指的是两个模块之间的关联程度。所谓松耦合指的是,两个模块之间的依赖关系简单清晰,即使两个模块有依赖关系,一个模块的改动不会或者很少影响到另一个模块。
高内聚和松耦合通常是一起出现的,高内聚有助于松耦合,松耦合又需要高内聚的支持。高内聚和松耦合的程序在可维护性、可读性、可扩展性上都会好很多。
高质量编码
要想编写高质量的代码,可以从设计风格、设计原则、设计模式、编程规范、重构技巧等等方向着手。
设计风格
现在主流的编程风格分为三种:面向过程、面向对象、函数式编程。
面向对象编程是其中相对流行的风格,而且大部分的设计原则、设计模式都是基于面向对象编程实现的。
设计原则
设计原则可以指导代码设计,它们都非常抽象,通常是在开发时给予指导意义。
常见的设计原则有 SOLID 原则、DRP 原则、KISS 原则、YAGNI 原则、LOD 原则等。
设计模式
大部分设计模式解决的是代码的可扩展性问题。
在设计模式领域,狭义的设计模式就是指 GoF 的《设计模式:可复用面向对象软件设计的基础》一书中包含的 23 种经典的设计模式。
这 23 种设计模式根据目的(模式是用来做什么的)可分为 3 种类型:创建型、结构型、行为型:
- 创建型设计模式主要解决“对象的创建”问题
- 结构型设计模式主要解决“类或对象的组合或组装”问题
- 行为型设计模式主要解决“类或对象之间的交互”问题
按照我自己对这些设计模式的理解程度对设计模式做排序,它们的详细分类如下:
- 创造型设计模式:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式
- 结构型设计模式:适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式
- 行为型设计模式:解释器模式、模板方法模式、职责链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式
编程规范
编程规范已经深入到编码当中,是一种更具体的解决代码可读性问题的方法。
编程规范更注重代码细节,比如,如何给变量、类、函数命令,如何写代码注释,函数不宜过长、参数不宜过多等。
重构技巧
重构是代码开发中非常重要的一个环节,持续重构是保持代码质量不下降的有效手段。
其实重构已经不算是方法论了,而是一种行为,通常重构是基于设计风格、设计原则、设计模式、编程规范这些理论才能做得更好。