一本关于设计模式的经典书籍
GOF的《设计模式》是很经典,但初学者也很难懂。。。这本书用最通俗易懂的语言,最简单明了的案例帮我们打开了设计模式这扇神秘的大门!设计之道设计,看上去很美设计没有标准,模式充满变化,我们对设计与模式的探讨,就是希望能从没有标准的设计中体验设计的乐趣,从充满变化的模式中寻求问题的解决之道。我这里所谓“设计没有标准”,其实并非没有标准,现实是设计的标准实在太多了。我们都希望找到最好的设计方案,然而什么是最好,每个人都有自己的“哈姆雷特”。满足客户需求的设训就是最好的,这个结论我想不会有人反对,前提是,怎样通过设计来满足客户需求?计划的设计和演进的设计通常来说,软件设讣不外乎两种方式:训划的设计和演进的设计。很多人看来,计划的设计更符合工程学的理念。如果你要建间茅屋,那么你只需夯好土墙,再胡乱堆放些茅草置于屋顶之上就可以了。然而,如果要你建一座苏州的拙政园,就必须事先有计划的设计了。哪里应该堆放假山,哪里应该开辟池塘,亭子的形状,院落的分布,乃至于园内的一花木,无不需要独具匠心。软件设计也是如此,且过之而无不及。接手项目的时候,首先考虑的不是编码,而是考虑整个系统的架构,根据需求考虑系统中的重人问题。模块的功能模块间的关系和系统分布的层次,都需要匠心独运,从一个抽象的层面来考虑演进的设计恰好与之相反,它是一种渐进的过程。它并不要求前期的设计有多么的完美,实现的需求有多么的完整,你只需要把现阶段考虑的问题编码实现就可以了,随着演进的深入,编码也会随之而修止,最后设计会逐渐丰满起来,经过一系列的方法,最后的设计也渐趋完美。你也许会认为“演进的设训”如此的简陋与平庸。没有计划,只会令设计一团遭。但我需要提陧你的是,虽然都是工程学,软件的设计并没有建筑设计那么简单。因为,你很难在设计之初,考虑到客户的全部需求,甚至于实现未来的扩展。在设计一开始,你能确信:你对客户的需求都理解∫吗?你能确定客户的需求不再变化吗?你设计的软件架构真的能满足需求吗?是的,你无法给出肯定的回答。总之我在这里不是想说服每个人,要采取哪一种设计方式。事实上,我也面临抉择的困难。过度设计,还是简单设计?在《解析极限编程—拥抱变亿》中为简单系统制定了四个评价标准,依次为(最重要的排在最前面)通过所有测试体现所有意图;避免重复;类或者方法数量最少:这些标准写出来简单,要根据这个标准来实现,就不是那么容易的事了。我相信,软件设计人员都希望自己的设计尽可能简单。然而,在设计时,我们不仅仅要考虑软件的功能设计之道我们还要考虑软件的性能、扩展性,模块间的耦合关系,系统的稳定、部署和更新,版本的管理,系统的安全,界面的友好程度。要想简单,何其之难!这是人士大声疾呼的口号,我也举双手赞成。问题是,我们需要让简单的事情,同时又有效。很多人在设计时,并不满足于实现眼前的功能。看到加法,他们可能还会想到乘法;虽然日前的需求是整数,他们可能想到今后可能会扩展到实数,甚至于复数。他们希望能利用某种设计,使其具冇更好的扩展性。从眼前的需求来看,可能是过度设计;然后对于未来,这个设计才是最完美的方案。问题不在于设计是否过度,关键还是在于设计的理念。是只做日前需要的事,还是未雨绸缪,想好今后的功能扩展?这个问题的答案还需要实际的项目丌发来检验,根据不同的需求,答案会因此而异需要设计模式吗?答案是肯定的,但你需要确定的是模式的应用是否过度?我得承认,世界上有很多天才的程序员,他可以在一段代码中包含种设计模式,也可以不用模式而把设计做得很好。但我们的目标是追求有效的设计,而设计模式可以为这个目标提供某和参考模型、设计方法。我们不需要奉的设计模式为圭臬,但合理的运用设计模式,才是正确的抉择很多人看过的《》,对这种模式也背得滚瓜烂熟。但重要的不是你熟记了多少个模式的名称,关键还在于付诸实践的运用。为了有效地设计,而去熟悉某种模式所花费的代价是值得的,因为很快你会在设计中发现这种模式真的很好,很多时候它令得你的设计更加简单了。其实在软件设计人员中,唾弃设计模式的可能很少,盲目夸大设计模式功用的反而更多。言必谈“模式”,并不能使你成为优秀的架构师。真正岀色的设计师,懂得判断运用模式的时机。还有一个问题是,很多才踏入软件设计领域的人员,往往对设计模式很困惑。对于他们来说,由于没有项目的实际经验,的思想也还未曾建立,设计模式未免过于高深了。其实,即使是非常有经验的程序员,也个敢夸口对各种模式都能合理应用。重构是必然的!既然我们无法给出一个完美的设计方案,因为客户的需求总是变化的,重构也就成为必然。问题是,这样没有添加任何功能的重构,你是否愿意为此付出精力、时间去完成。当客户要求的将要到来的时候,你还认为你的重构工作是必要的吗?有时候,软件设计常常身不由己。然而,纯从技术的角度来看,重构非但必然,而且重要。既然我们都明白,复杂的未尝就是好的,简单的也不一定是容易的。要保持你的设讣尽可能的简单,可能你还需要时时借助重构的利器,来“改善你既有代码的设计”。对于重构,给出了很多条款。这些条款并不是政治课本的教条,也不是“日月神教”的神奇咒语,念着它们就可以防身。这些条款确实很亘要,但你需要的是学会他后,然后忘记他,就象张无忌学太极拳那样。我不是故弄玄虚,事实上只有这样,亘构的精神才能完全融入到你的设计中。重要吗?我现在看一个设计方案的时候,更希望先看看,然后再看文档的实际描述。如设计之道果让我读一段代码,我希望能先看看类图,或许更容易理解代码的含义在世界里像是世界语,它便于程序员间的交流,让别人更容易理解你的意图。同时,在设计图的过程中,也是一种对思路的清理,对客户需求的把握,设讣思想的跟踪。是种基于对象的统一建模语言,它能够为系统设计提供清晰直观的设计。在面向对象世界里,的地位弥足轻重,甚至被称为是软件设计的一场革命。对于有计划的设计,的价值就体现得淋漓尽致。如果我们要清晰地表现模块的功能,模块间的关系和系统分布的层次,使用可以使设计师减少很多麻烦,同时降低了语义描述的义性。然而,如果我们在做演进的设计时还有那么重要吗?我们只需要对眼前的需求进行编码、测试,然后重构。可能我们只需要在中讨论设计方案,在预定技术框架内探讨实现的可能和细节。我们完全可以抛开繁琐而死板的设计,毕竞最能忠实体现设计思想的,不是文档,不是用例图或是什么类图,而是代码。那么,有多少人是这样想的?单元测试和其他软件的生命是什么,是质量!而保证质量的唯一方法,就是测试。传统的软件开发过程,强调首先进行需求分析,再从需求分析中抽象岀概要设计,进而作岀详细设计,然后编码,最后才是测试以验证代码的正确性。而测试驱动开发()改变了编码的过程,开发仅仅包括三方面的活动:编写测试用例,编码并进行测试,重构代码以消除重复代码使其更简单、更灵活、更容易理解。通过测试来驱动开发,听起来是那么的离经叛道,然而实施起来,又是那么合理、正确和简单,前提是:我们不能在一开始就获得正硝的设计!避免了对不完整需求造成的不成熟的设计。通过单元测试,保证了代码的正确性与高质量;通过重构,使设计更加简单、灵活设计之道设计,由你掌握前言:中有个准则,就是只做日前你需要做的。例如,我需要加法运算,你就没有必要实现乘法运算,因为这不是客户需要的。因此,在开发中,我们可以不去考虑程序对子未来的扩展性。“简单最好!”那么,是否就不需要设计∫呢?全于设计模式,是否也可以不去了解了呢?答案至少是否定的。因为客户的需求是“与时俱进”的,现在不实现,并不等于今后不实现。在实现中,不管是重构,还是重新设计,通过应用设计模式,能令你如虎添翼。关键不在于设计模式是否重要,而在于你怎么应用它,以及选择什么样的时机。总而言之,设计,由你掌握!从需求开始在我们的项目中,作费用结算的时候,客户要求将该过程与结果写入到日志文件中。不过他们的要求很善良,只需要知道日志记录结算开始与结束的时间而已。是的,按照的理念,我们只需要做好客户需要的事情就了。既然是这样,事情就好办,代码轻易而举就实现了结算程序将调用数据层的相关方法,访问数据库;为简单起见,我月累加数取代我用控制台输出来表示写日志写好这个,还差点什么?不错,我们还需要为类撰写相应的测试代码,做好单元测试。可能对于传统的程序员来说,更喜欢的是在编码完成后,再根据测试计划编写测试样例,最后泱试。但敏捷开发的要求却是测试先行,单元测试是必不可少的环节。不过,我认为单元测试毕竟只是一种于段。我们在实际的项日开发中,对于单元测试不可拘泥教科书的要求,按部就班地一步一步进行;而应该根据实际情况,比如开发者对话言的掌握程度,对设计的理解等等,来决定你单元测试的步骤,乃至于重构的步伐。设计之道在中打开这个测试类,并运行。毫无疑义,你会看到测试的绿灯全部都亮了。你可以在中看看控制台输出的结果。白然你也可以在方法中,故意将预期的值设置错误,来看看运行是什么情況,以及出现的错误提示信息。不过,这些都不是本文关注的重点。二、当需求改变了在中,客户的重要是举足轻重的。在客户提出需求的时候,你需要和他尽可能地沟通,并保证意见最后要达成一致。然而客户对产品的理解可能有时候会出现偏差,也许有时候对方的要求也会随着产品的应用而逐渐发生改变。所幸的是,这一次需求的改变,发生在项目开发过程中,且是在你和他结对交流的时候,最终发现的缺陷。因为客户认为,这个∏志过于简单了,并不利于今后对产品的维护。我得承认这是一个好的要求。事实上,日志记录得越详细,对于开发人员自己也是有好处的。最后,我们决定,日志不仅仅要记载结算的起止时间,还应该记载可能会出现的错误信息,最好还能记载这个结算旳过程代码,比如我们执行的是哪一个存储过程,读取」哪些表的数据,包括这些表的字段。然而有个不利的因素是,这个费用结算的过程可能会很频繁的使用。如果写入的日志太复杂了,矢否影响产品的性能?而且频繁写日志的话,日志文件会不会越来越大?如果我们这个产品己经非常健壮,还有必要去记载这些信息吗?毕竞有很多信息,对丁普通用户而言,并没有实际用处,反而干扰了他有效获取日志的有用信息。所以后来我们想到一个方法,就是将日志进行分级,从最简单到最详尽。用户在进行费用结算的时候,可以根据自身需要,选择日志的级别。无疑,这是一个令人满意的策略。三、如果不熟悉设计模式假设我们的开发人员对于设计模式一概不知,经过分析客户的需求,他会直接了当的做出如此的解决方案。首先定义三种级别的日志:只记录结算的起止时间和耗费的时间,同时还要记录结算后的结果。则除此之外,还要记录可能会出现的错误信息。而最详尽,它不仪包含了记录的信息,还包括记录结算的实现方法,如用到的存储过程,数据表和相应的字段。我们最初设想为这三种级别建立三个不同的私有方法,然后在方法中,引入个日志级別参数,然后根据日志级別的值,决定调用哪一个私有方法,例如:设计之道不用说,我们的程序员遇到麻烦了。因为在记录日志信息的时候,可能会在结算的前后来进行。也就是说,结算的那段代码必须放到记录日志的方法中,才可以实现。幸运的是,我们的程序员应该还具备重构的知识,他决定把结算的那一段代码专门抽取出来,形成一个单独的方法,冉放到日志方法中调用。“”,不是吗?很聪明的做法。好吧,我们来实现它吧,看看会是怎样?首先,实现专门的结算方法再来实现日志方法设计之道在这个方法中是类中的一个私有变量,用来保存结算后的结果。假设不使用这个变量,而是在方法中引入局部变量,那么方法就必须返回类型了,这个设计可够糟糕的!同样的,和也应该是通过私有变量传递值,否则这个日志方法就必须带上这两个参数了接着实现下面两个方法。我们已经注意到根据∏志级别的不同,最详尽的日志内容总是包含了其低一级日志的内容。并且,后两级日志没有包括性能的记录,因此记录的日志并未要求必须出现在结算方法的前后。剩下的代码就简单了设计之道嘿嘿,看起来还不错当然,与之相应的测试代码也要发生改变四、问题又出现了我们程序员都应该有这个信仰,就是:简单最好。我不喜欢那些常常卖弄自己水平的人仅仅为了一个简单的要求,却故意把代码弄得非常复杂,以为卖弄高深就是学问。其实不然。我倾向于简单的算法,即使它的性能稍差。因为性能差,我们还可以通过提升硬件等多种方式来解决;而如果整个项目都允斥着难于理解的算法,想一想,如果写代码的“牛人”走了而日前又需要对程序做改进。那么,项日的后仟者,在的压力下,面对这一大堆“高深”的算法,会是怎样的抓狂!?所以,从目前来看,以上实现的代码并没有什么不合适的地方。简单易懂,也完成了客户的需求。不过,很多时候事情并非尽如人意。客户的需求会随着对项目的跟进,而逐渐发生改变。周后,我们的客户提出了新的要求。首先,他希望这个日志功能,能够展现它更灵活的一面。不是死板的从最简单到最详尽,而是根据日志记载的内容,任意灵活的组合。原来的日志层次如图注
用户评论
介绍设计的书值得看看。这个不全。