前
奏
最近看完了《设计模式精解》这本书,感觉收获颇丰,为了不让时间带走我的收获,在此将我的一些感想和收获记录下来,以飨大众。
首先回顾一下历史,看看能不能激起某些同志的共鸣,耐心的看完下面的部分,多给我提提意见指指路
^_^
。
从大学三年级开始到将近工作一年的这段时间里,我的角色是一个代码编写者,这段时间的主要心理状态是一看到功能描述就会去想实现。大三下学期的时候写过一个
asp
的内容管理系统,那个时候完全没有代码复用,设计系统结构的概念,完全是见招拆招,有几个很壮观的页面的代码超过了
25k
,每当我看到这几个页面时我就很自豪(我终于可以写出
25k
的代码了),但是我从来没有维护过它们,不是没有
bug
,是看起来很头疼!毕业后的头半年写过一个
jsp
的内容管理系统,这是我头一次接触面向对象的语言,不过设计、实现的时候还是有很多在学校时做的
asp
系统的影子,几乎就是把
jsp
当
asp
用,不过就在这段时间里开始了解了
struts
,知道它是一个
mvc
框架,仅此而已,又看完了
java
编程思想,多多少少有了点对象的概念,知道多态继承封装是怎么回事,但是却不知道什么时候去使用它们。直到后来要做一个类似
web
容器的东东,看完了一个高手设计的开源框架的代码,又囫囵吞枣的读完了设计模式,于是开始对面向对象有感觉了,知道要针对接口编程,某些特定场景下要用某些设计模式。但是我仍然清楚的认识自己还停留在实现层次,如果给我一个系统让我设计,我理不出合理的软件架构,不知道怎么去设计可扩展的,结构清晰的,易使用的软件架构。我努力的想跳出那个圈,但是我找不到向上的阶梯
……
接下来的日子里,我做一些平台的维护工作,因为平台是各种模块的集合,如果用户使用平台出了问题,有可能是各种各样的模块的问题,这段时间里,我得以接触多个模块,学会了怎样快速理清软件系统的层次。后来,我承担了一些平台的需求分析,开始自己去思考怎么样设计软件的层次,由于缺乏经验,感觉这些工作都做得不好。但是这一切,都是我不可或缺的积累,我依稀能看到那个向上的阶梯
……
直到后来,我遇到了它(广告开始):《设计模式精解》。此书以一个实际的例子阐述了软件设计的过程,清晰的描述了系统设计应遵循的规则,让我真正理解了创建型模式,结构型模式,行为型模式的涵义。从此以后,让我
……
,实在是程序员,架构师等人之必备良书。等等,鸡蛋和西红柿都捐给希望工程吧,不要浪费
^_^
。(题外话:光有理论不实践不能深刻的理解理论,如果在理论的指导下实践会取得事半功倍的效果,如果我没有需求分析的经验,当我看这本书时不会有那么深的体会。我们在努力工作的同时,还是要多看看书拔高自己。)
正
题
首先阐述一下面向对象的一些基本概念。
什么是对象?就像《
java
编程思想》里说的那样,是属性与行为的集合吗?这只是实现层次的理解,从概念层次上讲,好的对象是一个能承担责任的载体,它对自己负责,能独立完成自己的工作。(像极了我们优秀的同事
^_^
);从规格层次上讲,对象是一系列可以被其他对象或自己调用的方法。
什么是多态?多态就是同一种事物表现出的多种形态,比如白马,黑马,灰马等等都是马,但是都是不同的马。映射到面向对象系统中就是一个抽象类的多种实现。
什么是继承?让一个类成为另一个类的特殊类型。这些特殊类型的类被称为父类的子类。
什么是封装?封装意味着任何形式的隐藏――
>
数据隐藏,类隐藏,实现隐藏。数据隐藏就是隐藏对象的内部属性;类隐藏就是隐藏具体类,将抽象类或接口暴露给客户;实现隐藏就是隐藏内部的实现,提供供用户调用的接口。
为什么要面向接口编程?接口能够有效对类功能进行分组,避免客户了解和他不相关的知识,另外,接口是需求中比较稳定的部分,而实现是和具体环境相关联的。
下面就以一个简单的例子《图形显示系统的设计》来说明一个软件设计的过程。
功能描述
要设计一个图形显示系统,该系统要支持在屏幕上或在文件中打印出四种图形:圆形,方形,三角形,五角形。
1.
建立分析
matrix
功能
|
显示在屏幕中
|
显示在文件中
|
取得图形位置信息
|
取得图形在屏幕中的位置信息
|
取得图形在文件中的位置信息
|
显示图形
|
根据位置信息在屏幕中打印图形(圆形,方形,三角形,五角形等)
|
根据位置信息在文件中打印圆形(圆形,方形,三角形,五角形等)
|
2.
根据场景确定系统使用哪种设计模式
在系统设计时,我们应遵循“先确定规格,后确定实现”的原则,因为规格表示系统的共同部分,而实现表示系统的特定部分。
我们先观察上面的矩阵的第一列。
看完第一列,我们发现,图形显示系统要完成图形的显示必须做两件事,第一件事是是取得图形的位置信息,第二件事是显示图形。
于是一个表示系统规格的基类就出来了。
DisplaySystem
+ getLocation();
+ display();
|
再看矩阵的第二行,我们发现,如果图形显示的场所(文件
/
屏幕)不一样,那么位置的计算策略也不一样。我马上想到了策略模式,那么怎样让策略脱离系统独立演化呢?用组合。
再看矩阵的第三行,我们发现,图形不一样,显示的逻辑也不一样。还有一个变化点就是,在文件中画出点的逻辑跟在屏幕中画出点的逻辑不一样。这个功能模块中存在两个变化点,为了可扩展性考虑,我们必须要让这两个点能独立演化。于是我想到了桥梁模式。
根据以上的分析,我们得到系统的细粒度的设计如下:
FileLocation
+ getLocation()
|
ConsoleLocation
+ getLocation()
|
由于缺乏专业建模工具,设计图暂且画成这样。
到此为止,我们看看现有的系统。该系统已经满足了现有的需求。如果以后新增了一个需求,要支持画六边形,那么我只要再创建一个继承于
Display
的
HexagonDisplay
。如果又增加了一个需求,要支持在远程屏幕上画图形,那么我们只需要再增加一个继承于
DrawDot
的
RemoteConsoleDraw
类。
那么到此结束了么?我们再仔细看看设计图。图中有三个继承体系:
Location
、
Display
、
DrawDot
,我们是不是又看到了抽象工厂模式的用武之地?关于怎样在此系统中加入抽象工厂模式就不再说明了。
回顾一下该系统设计中用到的模式:
设计模式类型
|
设计模式
|
创建型模式
|
抽象工厂模式
|
结构型模式
|
桥梁模式
|
行为型模式
|
策略模式
|
对三种类型的设计模式的介绍:
设计模式类型
|
说明
|
创建型模式
|
解决类或对象之间如何交互和如何分配职责的问题
|
结构型模式
|
解决如何正确的组合类或对象的问题
|
行为型模式
|
解决类或对象之间如何交互和如何分配职责的问题
|
结合这个例子,再看看这些概念,是不是理解更清晰了?
关于系统设计的一些注意事项:
1.
不要打算去设计一个完美的系统,我们永远无法预测用户会有什么样的需求。
2.
设计系统的时候要特别注意系统中的变化点,将无法预知的变化点提取出来让其独立演化。
3.
牢记“先确定规格,后确定实现”的原则。要不然我们会一头扎进无穷尽的变化的汪洋大海。
4.
根据场景定模式。每一种模式都有特定的适应场景。
5.
不要滥用设计模式。
后
记
曾几何时,苦于做面向对象系统设计不得其门而入(苦于怎样确定系统内的实体),于是苦寻系统设计法则,曾经见过这样一句名言:“根据名词确定类,动词确定行为”。当时觉得如获至宝,茅塞顿开。现在看来,这么做固然能设计出一个系统,但不一定能设计出一个高扩展性的系统。要设计出一个高扩展性的系统,必须让系统能够包容变化,变化也可以成为系统中的一个类(为了让变化独立演变),所以,我认为那句良言仅供参考。
另外,我觉得《设计模式精解》书中所说的“根据场景选用模式”非常经典,如果我们能在平时工作中多多留心,积累一些“特定场景下使用特定模式”的案例,再拿出来共享一下,我相信,我们人人都能成为优秀的设计师。
|
文件: |
面向对象的设计.rar |
大小: |
12KB |
下载: |
下载
|
|