GHawk

敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则)

开闭原则很简单,一句话:“Closed for Modification; Open for Extension”——“对变更关闭;对扩展开放”。开闭原则其实没什么好讲的,我将其归结为一个高层次的设计总则。就这一点来讲,OCP的地位应该比SRP优先。

OCP的动机很简单:软件是变化的。不论是优质的设计还是低劣的设计都无法回避这一问题。OCP说明了软件设计应该尽可能地使架构稳定而又容易满足不同的需求。

为什么要OCP?答案也很简单——重用。

“重用”,并不是什么软件工程的专业词汇,它是工程界所共用的词汇。早在软件出现前,工程师们就在实践“重用”了。比如机械产品,通过零部件的组装得到最终的能够使用的工具。由于机械部件的设计和制造过程是极其复杂的,所以互换性是一个重要的特性。一辆车可以用不同的发动机、不同的变速箱、不同的轮胎……很多东西我们直接买来装上就可以了。这也是一个OCP的例子。(可能是由于我是搞机械出身的吧,所以就举些机械方面的例子^_^)。

如何在OO中引入OCP原则?把对实体的依赖改为对抽象的依赖就行了。下面的例子说明了这个过程:

05赛季的时候,一辆F1赛车有一台V10引擎。但是到了06赛季,国际汽联修改了规则,一辆F1赛车只能安装一台V8引擎。车队很快投入了新赛车的研发,不幸的是,从工程师那里得到消息,旧车身的设计不能够装进新研发的引擎。我们不得不为新的引擎重新打造车身,于是一辆新的赛车诞生了。但是,麻烦的事接踵而来,国际汽联频频修改规则,搞得设计师在“赛车”上改了又改,最终变得不成样子,只能把它废弃。

OCP-fig1.JPG

为了能够重用这辆昂贵的赛车,工程师们提出了解决方案:首先,在车身的设计上预留出安装引擎的位置和管线。然后,根据这些设计好的规范设计引擎(或是引擎的适配器)。于是,新的赛车设计方案就这样诞生了。

 OCP-fig2.JPG

显然,通过重构,这里应用的是一个典型的Bridge模式。这个实现的关键之处在于我们预先给引擎留出了位置!我们不必因为对引擎的规则的频频变更而制造相当多的车身,而是尽可能地沿用和改良现有的车身。
说到这里,想说一说OO设计的一个误区。
学习OO语言的时候,为了能够说明“继承”(或者说“is-a”)这个概念,教科书上经常用实际生活中的例子来解释。比如汽车是车,电车是车,F1赛车是汽车,所以车是汽车、电车、F1赛车的上层抽象。这个例子并没有错。问题是,这样的例子过于“形象”了!如果OO设计直接就可以将现实生活中的概念引用过来,那也就不需要什么软件工程师了!OO设计的关键概念是抽象。如果没有抽象,那所有的软件工程师的努力都是徒劳的。因为如果没有抽象,我们只能去构造世界中每一个对象。上面这个例子中,我们应该看到“引擎”这个抽象的存在,因为车队的工程师们为它预留了位置,为它制定了设计规范。
上面这个设计也实现了后面要说的DIP(依赖倒置原则)。但是请记住,OCP是OO设计原则中高层次的原则,其余的原则对OCP提供了不同程度的支持。为了实现OCP,我们会自觉或者不自觉地用到其它原则或是诸如Bridge、Decorator等设计模式。然而,对于一个应用系统而言,实现OCP并不是设计目的,我们所希望的只是一个稳定的架构。所以对OCP的追求也应该适可而止,不要陷入过渡设计。正如Martin本人所说:“No significant program can be 100% closed.”“Closure not complete but strategic”

(下一篇就要讲LSP了,我觉得这是意义最为重要的OO设计原则,它直指当今主流OO语言的软肋,点出了OO设计的精髓。)

posted on 2006-01-18 00:26 GHawk 阅读(7563) 评论(7)  编辑  收藏 所属分类: 软件过程学习笔记

评论

# re: 敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则) 2006-01-18 11:54 Samuel Cai

你自己的例子?感觉和书上想阐述的想法不一样。  回复  更多评论   

# re: 敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则) 2006-01-18 12:14 GHawk

To Samuel Cai,
说的有道理。
写的时候一直在斟酌哪样的例子比较合适,因为OCP相当抽象,所以选出好的例子很难,要说明一定要以某种模式实现OCP很困难,我的这个例子有点类似书中OCP那章一开始那个Client/Server的例子。不过,要举出违反OCP的例子倒是不少。最典型的就是通过RTTI(运行时类型鉴别)+ switch 或是 if-else 来进行设计。这样的用法越多,封闭性就越差,模块的刚性也就越强。OCP主张在设计中采用多态等动态机制取代静态机制。当然,通过配置文件的方式进行模块的动态配置也是实现OCP的一种手段。  回复  更多评论   

# re: 敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则) 2006-01-18 16:58 啦啦啦

诚然.感觉Interface的引入是对OO的很大的补充,使人们不用再对"继承"的概念含糊不清了

比如AbstractRaceCar需要的是一个能够提供动了的东东,暂时叫他为"IEngeer",只要大小合适,能够提供动力即可.V10可知胜任,如果V8能够符合这个要求的话也行,甚至是舒马赫的双腿--只要他能把他的腿伸进去,我们就不用违心的用多继承说舒马赫也是从"IEngeer"派生而来的,呵呵  回复  更多评论   

# re: 敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则) 2006-01-18 18:07 江南白衣

一直觉得这本书改错名,严重的投机"敏捷"潮流.  回复  更多评论   

# re: 敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则) 2006-01-18 18:17 GHawk

的确有投机之嫌,说敏捷过程的东西太少了,就几章而已。^_^  回复  更多评论   

# re: 敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则) 2006-03-06 14:13 xiaofengown@sina.com

讲的比效通俗易懂  回复  更多评论   

# re: 敏捷软件开发 读书笔记 (3)——OO五大原则(2.OCP——开闭原则)[未登录] 2007-04-29 10:29

如果OO设计直接就可以将现实生活中的概念引用过来,那也就不需要什么软件工程师了!OO设计的关键概念是抽象。如果没有抽象,那所有的软件工程师的努力都是徒劳的。因为如果没有抽象,我们只能去构造世界中每一个对象。


太经典了,谢谢  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: