最近,同事、朋友跟我聊天的过程中,提到了设计模式方方面面的问题。随着面向对象、敏捷开发的深入人心,越来越多的程序员希望能够借助设计模式,使自己的代码更利于重用、更利于被人理解、可靠性更有保证。
不同的情况下需要用什么样的模式,如何实现这些模式,在各类著作中已经介绍的相当清晰了,但是关于设计模式实现的时机,却提的比较少。
过度设计 是指代码的灵活性和复杂性超出所需。如果我们在设计初期,就实现各类模式,进行完整的规划,随着需求的逐步修改,很可能出现大量的不再需要的设计,这完全不符合敏捷开发的思想。
设计不足 是指不良的开发方式导致后期难以维护。显然,如果我们不进行任何规划,随意的添加功能,就会使项目越来越混乱,以至于最后为了增加一些功能,不得不推倒重新设计。
不进行合理的规划是绝对不行的,而在初期就进行规划代价又太大,好像没有了解决的办法。但是,当你联想起TDD(测试驱动开发)的基本步骤,就会发现大部分的模式实现其实在重构过程中就能完成。
1.针对需求,编写测试用例;
2.编写权宜代码,使测试能够完全通过;
3.重构代码。
重构使代码更清晰、更易于维护,同时不需要初期花费大量的时间进行详细的规划。
模式痴迷 是指某人对模式过于依赖,以至于无法不在代码中实现模式。初学者为了练习所学的设计模式,会出现大量并不恰当的模式实现。熟练掌握各类设计模式的开发者,更也有可能出现这种依赖。在进行一项设计时,首先想到的就是它适用于哪种模式,甚至忘记了switch可能更简单、更易于理解。
在重构的过程中,什么情况下应该使用设计模式?应该用哪种模式?
代码坏味 | 重构方法 |
重复代码 |
形成Template Method |
方法过长 |
组合方法 |
条件逻辑太复杂 | 用Strategy替换条件逻辑 将装饰功能搬移到Decorator 用State替换状态改变语句 引入Null Object |
基本类型迷恋 | 用类替换类型代码 用State替换条件改变语句 用Strategy替换条件逻辑 用Composite替换隐函树 用Interpreter替换隐式语言 将装饰功能搬移到Decorator 用Builder封装Composite |
不恰当的暴露 | 用Factory封装类 |
解决方案蔓延 | 将创建知识搬移到Factory |
相似功能的类 | 通过Apapter统一接口 |
冗赘类 | 内敛Singleton |
类过大 | 用Command替换条件调度语句 用State替换状态改变语句 用Interpreter替换隐式语言 |
分支语句 | 用Command替换条件调度程序 将聚集操作搬移到Visitor |
组合爆炸 | 用Interpreter替换隐式语句 |
怪异解决方案 | 通过Adapter统一接口 |