编辑推荐
“给我一个支点,我就能撬起地球”
关键不在于力量有多大,而在于如何合理地利用力量。
软件设计同样如此
思想的确立,技巧的把握,将在很大程度上制约软件架构的合理性。本书力图通过大量的项目实践,并与软件设计思想完美结合,充分展示软件设计之美,以及设计“力量”的巧妙运用。
内容简介
书籍 计算机书籍
本书关注的焦点是软件设计,涵盖了大部分与设计有关的基本要素,包括面向对象思想、设计模式、重构、测试驱动开发、极限编程以及软件体系架构。其中,尤以设计模式为主,深入探讨了软件设计过程中的原则与模式,并结合大量的实例与代码演示了如何合理运用设计模式,改善程序模块的可复用性、可扩展性,实现模块间的松散耦合。全书将软件设计理论与项目实践完美地结合起来,使其告别了纯理论研究的空泛,具有现实的指导意义。
本书适用于所有希望提高软件设计水平的程序员、软件工程师,同时,对于软件设计师与系统架构师也具有一定的参考价值。
目录
第1篇 设 计 之 要
第1章 设计之道 2
1.1 计划的设计与演进的设计 2
1.2 架构的标准 4
1.3 过度设计,还是简单设计 7
1.4 需要设计模式吗 9
1.5 重构是必然的 10
1.6 UML重要吗 11
1.7 测试驱动开发 12
第2章 对象法则 14
2.1 面向对象思想 14
2.2 面向对象核心要素 15
2.2.1 封装 15
2.2.2 继承 18
2.2.3 多态 21
2.3 面向对象设计原则 23
2.3.1 单一职责原则 23
2.3.2 开放封闭原则 27
2.3.3 Liskov替换原则 29
2.3.4 依赖倒置原则 30
2.3.5 接口隔离原则 32
第3章 封装变化 35
3.1 设计模式之鹄的 35
3.2 如何封装变化 37
3.2.1 封装对象行为的变化 37
3.2.2 封装对象创建的变化 40
3.2.3 封装对象结构的变化 44
3.3 解耦具体依赖 47
3.3.1 配置文件与反射技术 49
3.3.2 表驱动法 51
3.3.3 惯例优于配置 53
3.3.4 依赖注入 53
第4章 体验重构 56
4.1 一个阶乘容器 57
4.2 代码的坏味道 58
4.3 需求发生变化 59
4.4 运用重构利器 61
4.5 引入设计模式 64
第5章 测试驱动开发 67
5.1 发现价值与生产价值 68
5.2 运用面向对象编程思想 72
5.3 适时小结 77
5.4 收获价值 77
5.5 无上之力 78
第2篇 .NET框架与设计模式
第6章 .NET中的工厂方法模式 82
6.1 “嫁祸江东”之计 82
6.2 WebRequest对象的创建 89
6.3 改造工厂方法模式 91
6.4 实现良好的可扩展性 98
6.5 惯例优于配置 100
第7章 .NET中的合成模式 102
7.1 字处理软件 102
7.2 .NET框架中的控件 109
7.3 “复合方式”的合成模式 113
第8章 .NET中的装饰器模式 123
8.1 一步一步走向装饰器模式 123
8.2 .NET框架中对流的处理 133
第9章 .NET中的迭代器模式 138
9.1 分辨对象的职责 138
9.2 实现迭代器模式 139
9.3 迭代器模式大观园 144
9.4 迭代器模式在.NET框架中的实现 146
9.5 通过yield return实现迭代器 149
9.6 C# 3.0对迭代器模式的支持 153
第10章 .NET中的策略模式 156
10.1 税务系统 156
10.2 利用委托实现策略模式 158
10.3 .NET框架中的Provider对象 161
第11章 .NET中的命令模式 166
11.1 考勤管理系统 166
11.2 命令模式在WF中的运用 169
11.3 合成模式与命令模式的结合 172
第3篇 媒体播放器的设计之旅
第12章 面向对象与接口分离 178
12.1 拙劣的设计 178
12.2 面向对象设计 180
12.3 接口分离 185
12.4 解除具体依赖 190
第13章 接口行为的适配 195
13.1 新的应用场景 195
13.2 “狼”与“羊”的关系 196
13.3 引入适配器模式 200
13.3.1 类的适配器模式 201
13.3.2 对象的适配器模式 203
13.4 适配器模式比较 206
第14章 接口行为的扩展 207
14.1 设计走向死胡同 207
14.2 考察适配器模式 208
14.3 引入访问者模式 211
14.4 非循环访问者模式 213
14.5 合理运用访问者模式 217
第15章 接口行为的装饰 219
15.1 不断变化的需求 219
15.2 考虑代理模式 221
15.3 引入装饰器模式 224
第4篇 设计模式应用实践
第16章 抽象工厂模式应用 228
16.1 报表组件 228
16.2 糟糕的设计 229
16.3 引入抽象工厂模式 231
16.4 工厂对象的使用 234
16.5 引入策略模式和桥接模式 236
16.6 适配器模式扩展抽象工厂结构 238
16.7 接口还是抽象类 239
第17章 建造者模式应用 243
17.1 装配设备对象 243
17.2 糟糕的设计 246
17.3 引入建造者模式 249
17.4 从容应对扩展 253
第18章 命令模式应用 255
18.1 安装向导 255
18.2 糟糕的设计 256
18.3 引入命令模式 259
18.4 进一步完善 261
18.5 分辨对象职责与变化 268
第19章 职责链模式应用 271
19.1 员工培训系统 271
19.2 设计模型 273
19.3 设计的重构 278
19.4 职责链模式 280
第20章 观察者模式应用 286
20.1 监控设备状态 287
20.2 引入观察者模式 288
20.3 事件与委托改进观察者模式 292
第21章 代理模式应用 297
21.1 显示设备控件 297
21.2 引入代理模式 298
21.3 完善设计 305
第22章 设计模式综合应用 310
22.1 话单转换工具 310
22.2 糟糕的设计 311
22.3 面向对象的设计思想 313
22.4 引入策略模式 314
22.5 需求发生变化 318
22.6 引入模板方法模式 318
22.7 合理的设计才是最好的设计 321
22.8 引入桥接模式 322
22.9 分离接口 330
22.10 引入抽象工厂模式 334
第5篇 .NET体系架构
第23章 软件体系架构 342
23.1 分层架构模式 343
23.2 分层架构模式之优劣 345
23.3 PetShop的架构版本演化 346
23.4 PetShop 4.0的系统架构 349
第24章 数据访问层 355
24.1 数据库样式 355
24.2 数据对象 357
24.3 SQL语句之瘤 362
24.4 运用ORM的思想 363
24.5 资源库模式与工作单元模式 367
24.6 事务的处理 369
24.7 具有简单工厂特质的抽象工厂模式 372
24.8 服务定位器模式 374
第25章 消息处理 376
25.1 MSMQ的实现 376
25.1.1 消息处理模块的组成 376
25.1.2 消息接口 377
25.1.3 消息接口的实现 377
25.1.4 消息工厂 380
25.1.5 后台处理应用程序 382
25.1.6 引入策略模式 384
25.2 分布式处理 385
第26章 ASP.NET缓存 387
26.1 ASP.NET缓存概述 387
26.2 SqlCacheDependency特性 390
26.2.1 利用aspnet_regsql工具 390
26.2.2 利用SqlCacheDependencyAdmin类 393
26.3 ASP.NET缓存在PetShop 4.0中的实现 394
26.3.1 CacheDependency接口 394
26.3.2 CacheDependency实现 395
26.3.3 CacheDependency工厂 396
26.3.4 引入门面模式 398
26.3.5 引入代理模式 401
第27章 业务逻辑层 405
27.1 与领域专家合作 405
27.2 业务逻辑层的模式应用 408
27.3 PetShop的业务逻辑层 409
27.4 与数据访问层的通信 413
27.5 面向接口设计 415
第28章 表现层 419
28.1 页面控制器模式 419
28.2 用户管理 422
28.2.1 Profile特性 423
28.2.2 Membership特性 427
28.3 ASP.NET控件 434
28.3.1 自定义控件 436
28.3.2 用户控件 440
28.3.3 登录控件 441
28.3.4 Master Page 442
28.4 MVC模式 444
28.5 表现层的演变 448
参考文献 449
前言
我希望告别冗长的前言,仅述说第2版的变更。写作第2版的我,疯狂地吸收了诸多大师的设计思想,这一点可以从参考文献的前后差别看到端倪。这两年以来,我又参与了几个项目的设计与开发工作,所谓“实践出真知”,在佐证大师观点的同时,自己对设计的认识更进了一步。或许,第2版不会比第1版优秀太多,但至少会减少诸多不足。囿于版本,我无法做出新的突破。我期待能创作一本全新的书,全面论述我对软件设计的认识。现在的我,还不足以写出梦想中的软件设计之道。
言归正传。
整体而言,我对第1版的所有章节都进行了一定程度的修订。或者更正了过去的错误,或者进一步完善了原有内容。本书的内容仍然是散漫而自由的,然而形散而神不散,大体遵循了设计的基本原则。
在第1篇“设计之要”中,我新增了“对象法则”一章,言简意赅地介绍了面向对象思想的核心要素与设计原则。这基于我的一贯理念,即设计模式的核心本质是面向对象设计思想的运用。只有掌握了面向对象设计思想,才能真正体会设计模式的精髓,并将其运用在实际的项目开发过程中。“对象法则”一章可以有机地与“封装变化”一章结合起来,再加上第23章“软件体系架构”的内容,基本上勾勒出软件设计的脉络,从面向对象思想到设计模式,再到软件体系架构。
在“封装变化”一章中,我不仅完善了项目实例,还增加了关于如何“解耦具体依赖”的几种技巧。对于软件设计而言,这是非常有益的指导。我整个儿删去了第1版的第5章“设计,由你掌握”,并将其中的部分内容转移到“封装变化”一章中。这使得第1篇的内容更为紧凑,虽然删去了讨论极限编程的相关内容,却可以使得我们能够更加关注于设计,而不是方法学。
第2篇“.NET框架与设计模式”增加了对.NET 3.X的源代码分析。我无法做到与时俱进,因为.NET 4.0即将走进.NET开发人员的程序生活。或许在本书出版之后的不久,还会有5.0,6.0……我只是希望我的书不要被时代抛弃得太远。好在设计模式本身属于经典,而经典总是能够经得起时间考验的。本书讲述经典,自然能讨得一定好处。
更新最明显的是迭代器模式在.NET中的实现。C# 2.0引入的yield return以及.NET 3.0引入的Lambda表达式都为迭代器模式在.NET中成为一种惯用法贡献了一份心力。我对此的分析,可以在一定程度上帮助读者更好地理解迭代器模式。在第2篇中,我新增了一章“.NET中的命令模式”,通过解析.NET 3.0引入的WF(Windows Workflow Foundation),展现命令模式的非凡价值。第2篇的内容虽然与.NET平台息息相关,但对于其他平台的开发人员而言,仍有可观之处。我在撰写本书第2版时,同样参考了Java平台的设计理念,以及Ruby中的设计模式。
从章节名称来看,我对第3篇“媒体播放器的设计之旅”进行了颠覆性的革新。事实不然,虽然内容仍有调整,但并未动摇其根本。在对本篇进行修订时,我扮演了一名重构者的角色,利用重命名和搬移内容的方法,极大地改善了既有章节的合理性。我抛开原有的以设计模式为核心的论述方式,转而从软件设计的角度看待问题。模拟真实的软件开发,我讨论了如何运用面向对象设计思想,如何对接口进行分离。当客户需要引入第三方软件时,我提出了接口适配的方案。当需求发生变化时,我则对接口行为进行了扩展或装饰。
第4篇“设计模式应用实践”仍然体现了本书的重要价值。我对第18章“命令模式应用”的实例进行了极大的完善,使得该实例在表现命令模式方面,更加丰富与完整。第19章“职责链模式应用”完全面貌一新,替换为最近完成的一个项目实例,并通过对领域进行建模,辅以用例图、时序图、通信图和类图推导详细设计,展现了“用例驱动开发”设计思想的冰山一角。
本书对软件架构着墨不多,主要的架构思想均放在第5篇“.NET体系架构”中。利用PetShop实例,对于指导读者初窥架构之美,仍有不可低估的作用。第2版对软件体系架构的内容有所补充与增强,更多地引入了企业应用架构模式和领域驱动设计的内容。第23章“软件体系架构”算得上是技术架构的入门读物,主要介绍了分层架构模式与相关设计要素。在第24章“数据访问层”中,我特别引入了.NET 4.0中的Entity Framework,算是一次有益的尝鲜。利用这样的ORM框架,还可以极度方便地实现资源库模式与工作单元模式,在诸多分层架构中,我们都可以看到它们的身影。在第28章“表现层”中,我设想了如何在PetShop中引入ASP.NET MVC框架。我本希望能有大量篇幅介绍Silverlight,以及MVP模式的运用,如此对于.NET的表现层设计方才显得完整。可惜我对Silverlight所知不多,心有余而力不足。
第2版还有诸多变化不能体现在目录中。例如,我对本书的全部设计图进行了更新,更加准确、完善和美观,并保持了图形风格的一致性。第2版加入了诸多注解,大多数内容都是正文的补充与扩展,乃至思想点滴。阅读这些注解,可以帮助读者更好地理解我的设计意图,获得更多的模式知识。
本书面对哪些读者?读者又该如何阅读本书?第1版前言已经给出了答案。本书的再版并不打算彻底改头换面。
本书希望能够持续演进,敬请读者提出宝贵意见,并通过bruce.e.zhang@gmail.com联系我。如需获取本书代码,以及了解后续可能给出的勘误与更新,可以访问我的个人主页http://www.agiledon.com。
非常荣幸能够邀请到西门子中国中央研究院首席架构师李伟先生,InfoQ中文站总编辑霍泰稳先生,微软MVP朱永光先生以及IT168技术频道资深编辑、微软MVP胡铭娅小姐拨冗为我写序。四篇序言各有特色,通过他们的序,可以了解他们的技术心得与心路历程。寥寥千言,或许已胜过我的数十万文字。这样缤纷的文章,无疑为本书增色添彩。
好了,除了致谢,我不打算重复唠叨了。
钱锺书先生认为,献书仿佛魔术家玩的飞刀,放手而并没有脱手。随你怎样把作品奉献给人,作品总是作者自己的。可我还是希望把本书献给我的孩子——子瞻。当他宁静地呆在母亲肚子里时,本书的第2版同样也在孕育之中。现在,子瞻已经过了周岁生日,没有什么礼物可以比得上这本书更加让我感到自豪。我还要把本书献给我亲爱的妻子。写作虽然痛苦,可哪里及得上你分娩痛楚的万分之一。抚养子瞻的辛劳,更让虚弱的你身心憔悴。本书献给你,可否给你一丝安慰?
感谢我的父母。尤其感谢我的母亲。这一年多以来,调皮的子瞻折磨得您腰酸背痛,您却没有任何怨言,反而甘之如饴。我能有时间写作本书,您功不可没。
书一旦出版就不再属于作者。余下的,交给读者去品评吧!
2010年3月
序言
在InfoQ中文站.NET社区首席编辑朱永光介绍张逸,并希望邀请其加入编辑团队之后,我特别在网上找到张逸的相关资料研读,并粗略翻阅了他的著作《软件设计精要与模式》及译著《WCF服务编程》。一番考察之后,认为其符合InfoQ编辑人员所必备的两个特点:态度认真和技术扎实,然后郑重向其发出邀请。最终,张逸答应了我们的邀请,而我也为能和这样一位优秀的架构师合作而荣幸。通过其在InfoQ中文站上发表的作品,我和永光均为当初的决定欣慰,而张逸的作品也让网站.NET社区的内容更加充实。
很长一段时间以来,与模式相关的话题都特别引人注目。在去年InfoQ中文站举办的QCon北京大会上,来自知名网站eBay的架构师Randy Shoup介绍了eBay架构设计过程中的经验,场面之热烈,让很多参会者现在依然记忆犹新。在今年QCon北京大会上,Jolt图书大奖获得者Michael Nygard会带来他在系统设计过程中的反模式,虽未开场,已有多位朋友表示对此非常期待。诚然,在软件研发过程中,要找到一劳永逸的“银弹”并非易事,但类如“模式”和“反模式”这样的经验总结总会给后来者一些启发。
每个软件系统都有其独特的一面,研发所用的技术或者平台也多有不同,但仔细考察其背后的设计思想,总能发现几丝共性。正是这些共性经过抽象之后,形成模式,然后被后来者不断传承和演进,使得我们的软件系统愈加庞大和健壮。希望通过本书,读者能够了解作者张逸对技术的真诚,也能够帮助自己在软件设计的道路上找到知音和共鸣。
霍泰稳
InfoQ中文站(infoq.com/cn)总编辑
媒体评论
从实践分享的视角来看,书的内容编写地非常认真。作者从自身工作的经历,分事了自己对软件设计的理解,并以设计原则这样的方式,来分享最宏观层面上的要点。总结、思考的分量,可见一斑。本书有些章节很有新意,注意到了利用自身实践过的设计模式,以真实示例的方式来介绍如何灵活使用各种设计模式。此举对读者的实际工作,颇有帮助,愿为推荐。
西门子中国中央研究院,首席架构师
【插图】