设计模式之认识设计模式的重要性
为啥要学习设计模式
1.对于我来说目前最直接的目的就是应对接下来的面试和涨薪;
2.学习设计模式可以让我在开发中能提高效率,降低bug
3.学习设计模式可以让我了解框架源码甚至以后都能开发出高质量的开源项目
评判代码质量好坏的标准
总结一句话,就是该程序拥有良好扩展性,维护方便,代码可读.
接下来我们来学习一下这些代码质量标准
可维护性
我们首先来看,什么是代码的“可维护性”?所谓的“维护代码”到底包含哪些具体工作?落实到编码开发,所谓的“维护”无外乎就是修改 bug、修改老的代码、添加新的代码之类的工作。
所谓“代码易维护”就是指,在不破坏原有代码设计、不引入新的 bug 的情况下,能够快速地修改或者添加代码。所谓“代码不易维护”就是指,修改或者添加代码需要冒着极大的引入新 bug 的风险,并且需要花费很长的时间才能完成。
更细化地讲,如果代码分层清晰、模块化好、高内聚低耦合、遵从基于接口而非实现编程的设计原则等等,那就可能意味着代码易维护。
除此之外,代码的易维护性还跟项目代码量的多少、业务的复杂程度、利用到的技术的复杂程度、文档是否全面、团队成员的开发水平等诸多因素有关
可读性
代码的可读性应该是评价代码质量最重要的指标之一
我们需要看代码是否符合编码规范、命名是否达意、注释是否详尽、函数是否长短合适、模块划分是否清晰、是否符合高内聚低耦合等等
实际上,code review 是一个很好的测验代码可读性的手段。
如果你的同事可以轻松地读懂你写的代码,那说明你的代码可读性很好;如果同事在读你的代码时,有很多疑问,那就说明你的代码可读性有待提高了。
可扩展
可扩展性也是一个评价代码质量非常重要的标准。
它表示我们的代码应对未来需求变化的能力。
跟可读性一样,代码是否易扩展也很大程度上决定代码是否易维护。
代码预留了一些功能扩展点,你可以把新功能代码,直接插到扩展点上,而不需要因为要添加一个功能而大动干戈,改动大量的原始代码。
其他评价标准
简洁性
有一条非常著名的设计原则,你一定听过,那就是 KISS 原则:“Keep It Simple,Stupid”。
这个原则说的意思就是,尽量保持代码简单。
代码简单、逻辑清晰,也就意味着易读、易维护。
我们在编写代码的时候,往往也会把简单、清晰放到首位。
思从深而行从简,真正的高手能云淡风轻地用最简单的方法解决最复杂的问题。
这也是一个编程老手跟编程新手的本质区别之一
可复用性
代码的可复用性可以简单地理解为,尽量减少重复代码的编写,复用已有的代码。
比如,当讲到面向对象特性的时候,我们会讲到继承、多态存在的目的之一,就是为了提高代码的可复用性;
当讲到设计原则的时候,我们会讲到单一职责原则也跟代码的可复用性相关;
当讲到重构技巧的时候,我们会讲到解耦、高内聚、模块化等都能提高代码的可复用性。
可见,可复用性也是一个非常重要的代码评价标准,是很多设计原则、思想、模式等所要达到的最终效果。
可测试性
代码的可测试性是一个相对较少被提及,但又非常重要的代码质量评价标准。
代码可测试性的好坏,能从侧面上非常准确地反应代码质量的好坏。
代码的可测试性差,比较难写单元测试,那基本上就能说明代码设计得有问题。
如何写出高质量的代码
要写出高质量代码,我们就需要掌握一些更加细化、更加能落地的编程方法论,这就包含面向对象设计思想、设计原则、设计模式、编码规范、重构技巧等等
面向对象、设计原则、设计模式、编程规范、重构,这五者有何关系
面向对象
面向对象编程因为其具有丰富的特性(封装、抽象、继承、多态),可以实现很多复杂的设计思路,是很多设计原则、设计模式编码实现的基础。
接下来的7项是必须掌握的
- 面向对象的四大特性:封装、抽象、继承、多态
- 面向对象编程与面向过程编程的区别和联系
- 面向对象分析、面向对象设计、面向对象编程
- 接口和抽象类的区别以及各自的应用场景
- 基于接口而非实现编程的设计思想
- 多用组合少用继承的设计思想
- 面向过程的贫血模型和面向对象的充血模型
设计原则
设计原则是指导我们代码设计的一些经验总结。
设计原则这块儿的知识有一个非常大的特点,那就是这些原则听起来都比较抽象,定义描述都比较模糊,不同的人会有不同的解读。
所以,如果单纯地去记忆定义,对于编程、设计能力的提高,意义并不大。
对于每一种设计原则,我们需要掌握它的设计初衷,能解决哪些编程问题,有哪些应用场景。
只有这样,我们才能在项目中灵活恰当地应用这些原则。
对于这一部分内容,你需要透彻理解并且掌握,如何应用下面这样几个常用的设计原则。
- SOLID 原则 -SRP 单一职责原则(即:一个类只能承担一个事情)
- SOLID 原则 -OCP 开闭原则(即:实现不可修改,但可面向扩展)
- SOLID 原则 -LSP 里式替换原则(即:子类型能够替换它们的基类型)
- SOLID 原则 -ISP 接口隔离原则(即:抽象不持有特定逻辑,应持有实现的公有逻辑)
- SOLID 原则 -DIP 依赖倒置原则(即:高底层不能互相依赖,应同时依赖抽象)
- DRY 原则(即:不做重复的事,不写重复类似的代码)、KISS 原则(即:尽量简单的代码,让代码更容易被别人理解)、YAGNI 原则(即:只着眼必需的功能,不添加认为可能需要的功能)、LOD 法则(即:类应减少被外界直接访问的机会,类与类之间避免直接通信)
设计模式
设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。
大部分设计模式要解决的都是代码的可扩展性问题。
这一块的学习难点是了解它们都能解决哪些问题,掌握典型的应用场景,并且懂得不过度应用。
经典的设计模式有 23 种。
创建型
常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。
不常用的有:原型模式。
结构型
常用的有:代理模式、桥接模式、装饰者模式、适配器模式。
不常用的有:门面模式、组合模式、享元模式。
行为型
常用的有:观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式。
不常用的有:访问者模式、备忘录模式、命令模式、解释器模式、中介模式。
编程规范
编程规范主要解决的是代码的可读性问题。
编码规范相对于设计原则、设计模式,更加具体、更加偏重代码细节。
即便你可能对设计原则不熟悉、对设计模式不了解,但你最起码要掌握基本的编码规范,比如,如何给变量、类、函数命名,如何写代码注释,函数不宜过长、参数不能过多等等。
这块可以参考阿里的<<JAVA开发手册>>
重构
在软件开发中,只要软件在不停地迭代,就没有一劳永逸的设计。
随着需求的变化,代码的不停堆砌,原有的设计必定会存在这样那样的问题。
针对这些问题,我们就需要进行代码重构。
重构是软件开发中非常重要的一个环节。
持续重构是保持代码质量不下降的有效手段,能有效避免代码腐化到无可救药的地步。
如何重构和重构的应用场景
而重构的工具就是我们前面罗列的那些面向对象设计思想、设计原则、设计模式、编码规范。
实际上,设计思想、设计原则、设计模式一个最重要的应用场景就是在重构的时候。
我们前面讲过,虽然使用设计模式可以提高代码的可扩展性,但过度不恰当地使用,也会增加代码的复杂度,影响代码的可读性。
在开发初期,除非特别必须,我们一定不要过度设计,应用复杂的设计模式。
而是当代码出现问题的时候,我们再针对问题,应用原则和模式进行重构。
这样就能有效避免前期的过度设计。
需要掌握重构的点
1.重构的目的(why)、对象(what)、时机(when)、方法(how);
2.保证重构不出错的技术手段:单元测试和代码的可测试性;
3.两种不同规模的重构:大重构(大规模高层次)和小重构(小规模低层次)。
这五者之间的关系
本质都是为了提供代码的质量,提高开发效率
从我的角度来讲
如果这个设计模式是一本秘籍的话,面向对象是内功心法,基础中的基础,也是其他四项的根源;设计模式就是招式;设计原则是武器;编程规范招式的套路;重构就相当于把其他四项掌握了后,根据实际场景优化招式,出招的套路,甚至还可以夯实基础
官方解读
关于面向对象、设计原则、设计模式、编程规范和代码重构,这五者的关系我们前面稍微提到了一些,我这里再总结梳理一下。
- 面向对象编程因为其具有丰富的特性(封装、抽象、继承、多态),可以实现很多复杂的设计思路,是很多设计原则、设计模式等编码实现的基础。
- 设计原则是指导我们代码设计的一些经验总结,对于某些场景下,是否应该应用某种设计模式,具有指导意义。比如,“开闭原则”是很多设计模式(策略、模板等)的指导原则。
- 设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。应用设计模式的主要目的是提高代码的可扩展性。从抽象程度上来讲,设计原则比设计模式更抽象。设计模式更加具体、更加可执行。
- 编程规范主要解决的是代码的可读性问题。编码规范相对于设计原则、设计模式,更加具体、更加偏重代码细节、更加能落地。持续的小重构依赖的理论基础主要就是编程规范。
- 重构作为保持代码质量不下降的有效手段,利用的就是面向对象、设计原则、设计模式、编码规范这些理论。
参考资料
1.设计模式之美