设计引导---设计模式基础
新手阅读Gof的《设计模式》有点难度,这里,要讲述的是,帮助大家奠定一下基础,使大家更好的去学习设计模式,去提升我们的思想,设计包含着抽象,又有些哲学,静下心来,你也可以学到优秀程序员的技术。
设计模式,起初是从建筑学中开始发展的。在此来讲个故事。
很久很久以前~~~(^_^),有一个建筑师,他修建了许多建筑,当地的人都十分尊敬他,因为他修建的房屋,是最牢固最美观的,但是他自己一直在问自己:“质量可以客观评价吗?”这位建筑师最感兴趣的一种美就是建筑质量:是什么让我感觉一个建筑设计是优秀的?
“评价一个建筑物是否美观”不仅仅是一个品味的问题。还需要通过可以衡量的客观标准来描述美观程度,比如质量,创意什么的。
我们软件的构建,也如同建筑学一样。需要设计,需要规划,它们有太多的相似的地方了。
我们也可以试着问自己:
优秀设计能表现而劣质设计不能表现什么?
劣质设计能表现而优秀设计不能表现的又是什么?
嗨!是否很矛盾呢?
没关系,故事还没讲完,建筑师观察了许多的建筑,城镇,街道,以及人们的生活环境。他发现,对于任何特定的建筑物,优秀的结构之间,总有一些相同之处。
建筑结构不相同,他们类型相同,尽管如此,他们仍是高质量的。
比如说我们每天使用的电脑,新产品的型号不同,但是他们终究是电脑,他们既然要销售,电脑就必须是高质量的。(你见过劣质电脑,能打铺天盖地的广告吗?)
建筑师通过这样的方式,观察解决相似问题的不同解决方案,一步步缩小他的关注焦点,他可以洞察出优质设计之间的相似之处,并把这些相似之处称为”模式”。
聪明的建筑师,把模式定义为“在某一个情景下的问题解决方案”。
每个模式,通过一种让你可以无数次使用这一解决方案、而不必再次重复同样的工作方式,描述一个在我们环境中重复出现的问题,并描述该问题解决方案的核心。
用简单的例子来描述一下这个有点复杂的概念:
建筑师需要修建一个庭院。
然后建筑师就会对于这个庭院有自己的构思:庭院可以享受阳光,享受星辰,要有私有的户外空间,需要些花花草草,有条件修建个小水池也不错。
然后建筑师,再向庭院主人详细问下个人的独特需求,然后建筑师就能开工。
在这里,建筑师的思考过程,就是我们所提到的模式,模式它有一个名称,在这里就是个庭院模式。然后他有个目的:帮助人们在其中生活。
为什么说这个庭院是一个优秀的庭院?建筑师修建了许许多多的庭院,他知道什么样的庭院才是适合人们的,符合人们习惯的,他有经验。然后它可以复用自己的经验,优秀的建筑师所设计的,一定是美的。
经验,可以使人们少走弯路,借鉴经验,从而加速达成目的。
模式几乎存在所有的设计问题中。
每个模式描述,都由下面4个组成部分:
- 模式的名称
- 模式的目的,它要解决的问题
- 我们如何实现它
- 为了实现它我们必须考虑的限制和约束
建筑师有一颗追求美的心。
好啦^_^,故事讲完啦,我们回到正题,软件设计模式。
“四人组”的《设计模式》是一部经典之作,很经典。
也许你都看过这本书了,知道这里面收录了23个模式。
在这需要认识到的是:
这几位作者并不是书中这些模式的创建者。几位作者识别除了那些已经存在于软件社群中的模式,“从特定问题的优质设计中学到的经验”。
任何一个模式描述都需要包括下面的基本要素:
名称 | 每个模式都有一个独一无二名称,人们用名称来鉴别模式 |
意图 |
模式的目的 |
问题 | 模式视图解决的问题 |
解决方案 | 对于自己出现的场景中的问题,模式怎样提供一个解决方案 |
参与者和协作者 |
模式包括的实体 |
效果 | 使用模式的效果,使用模式的同时研究其约束 |
实现 | 怎样实现模式。实现只是模式的具体表现形式。 |
Gof参考 | 在四人组的书中得到更多信息的位置 |
现在大家应该知道什么是设计模式了吧?现在再来完成一个大家疑惑的问题。
为什么要学习它们?
我们知道,学习写模块化的软件,能使软件复用。
现在要让大家知道,学习设计模式,能够复用解决方案,通过复用已经建立的设计,能为自己遇到的问题找到更高的起点,并避免了绕弯路。
受益于学习别人的经验。不必再为普通、重复的问题重新设计解决方案。有没用听起来很热血澎湃的感觉?最起码我是如此,代码重用不厉害,思想重用才厉害^_^。
第二点:
建立通用的术语,在交流于协作时,都需要一个共同的词汇基础、一个对问题的共同观点。设计模式在项目的分析和设计阶段提供了一个通用的参考点。
第三点:
对于问题、设计过程和面向对象,模式给你一个更高的层次的视角。你能从过早处理细节的通病中解放出来。(别以为处理细节不严重,繁琐的细节,让我崩溃,深有感触T-T)
不好理解这一点? 没关系,看个简单的模拟场景:
假设有两个木匠正在讨论如何为橱柜制作抽屉的问题。
木匠1:”你认为我们应该怎样制作这些抽屉呢?“
木匠2:“我想我们应该这样做结合部分,在木材上直锯下去,然后回转45°锯,然后再直锯下去,再朝另一个方向回转45°锯,再....然后......”(他在扯细节问题!!)
现在,你的的工作就是弄明白他们究竟在说些什么!看看分解之后的:
这里有些夸大了,真正的木匠师傅,并不会真的在细节的层次上说话,他们会用专业术语。
木匠1:我们应该用一个燕尾接合还是一个斜面接合?
这就是上面说的,建立通用术语,然后在高层次讲述问题。假如让你选择和他们其中一个人合作,你会选择谁?
模式能让我们同时看到树木和森林。
第四点:
学习设计模式,最重要的原因:它,能改表你的思想,让你成为更有力的分析者。
第五点:
它能提高你的效率,头脑思考的效率。别人是单核,而你是双核,这多么爽呀?
五点足够让你很有成就感了,其实好处不仅仅只有这些。
当在团队中,设计模式既可以帮助单个开发者学习,也可以帮助团队开发。这是因为,团队中的低级成员看到懂得设计模式的高级开发者从模式中获益,于是这些低级成员也想得到这些好处,这为他们学习这概念提供了有理的动机。
大多数设计模式还让软件更具可修改性,需求永远都在变,能适应变换的设计模式,让维护软件成为一种轻松的工作,还有什么理由不去学习?
我们知道,底层建筑决定高层建筑,在某种程度上,高层建筑能也能反馈底层建筑更多的信息。
在设计模式被正确传授时,可以大大增加学习者对基本面向对象设计原则的理解。(对于这一点,我是深有感触)在我学习设计模式时,使用它们来说明基本面向对象概念(封装、继承、多态等)在你学习了一些设计模式之后,即使你并不直接使用设计模式,你也会在自己的设计问题中使用这些策略。
设计模式还有一个优点,能让你或你的Team可以为不需要巨大继承体系的复杂问题创建设计方案。
总结:
学习这些可以帮助你:
- 复用现有的、高质量的、针对常见的重复出现问题的解决方案。
- 建立通用的术语,改善团队内部的沟通。
- 将思考转移到更高的视角。
- 判断是否拥有正确的设计,而不仅仅是一个可以运行的设计。
- 改善个人学习和团队学习。
- 改善代码的可修改性。
- 促进对改良设计的选用,升值在没有明确使用模式的时候。
- 发现“庞大的继承体系”的替代方案。
(吐血,下面又是第二写!!!自动保存个又坑我。以后再也不拿这个网页写随笔!)
好处差不多讲完了,现在来看些能够提高理解设计模式的具体方法。
has-a关系和is-a关系:
为什么要讲这个关系?园子里其实有人已经讲过这两个关系。我觉得这两个关系本该通俗易懂的,用简单的例子里整合一下,免得新手再去找相关关系去理解,太麻烦。(知道此关系的可以跳过此处,看看下面的UML介绍^_^)
has-a关系:
一个类“包含”另一个类。
一个简单的比喻就是,汽车他就是一个has-a的关系,汽车由各种配件组成,方向盘,发动机,轮胎等。
使用组合的可以把简单的东西组合成一个系统。组合就意味着可替换,一部分坏了,你可以选择修,也可以选择换。换好之后意味着,整个系统依旧良好的运行。
组合还有个优点,使用组合可以独立创建系统和子系统,更重要的是可以独立的进行测试和维护。(我深知其中好处,各种复用啊)
组合有两种类型,一种是关联(也叫组合,为了区别一下,我用关联),一种聚合。
关联:汽车就是关联,它由各个组件组合而成。
聚合:轮胎就是个很好的例子。
is-a关系:
“是一个”关系。看看图:
UML图可能大家还没熟悉,下面我也会简单介绍一下,帮助大家打下阅读UML图的基础。
在这里我可以说:狗是一种动物,代码表示就如下
Dog D=new Dog(); Mammal M = D;
这没错,狗和头有关系,但我们不能这么写:
Dog D = new Dog(); Head H = D;
这明显是错的,狗有头,但有头的不一定是狗,它可以是别的。比如猫。
在这个图的关系中,我们还可以给狗命名,就好像这样写:
Dog D = new Dog(); Nameable N = D;
它运行的很好,也很自然,一个名字代表一条狗。
在这个关系图中,我们用到了继承和接口。
我们知道,能继承的不仅是基类,它也可以是接口。
继承和接口都是构成is-a关系的简单而有效的证据。啰嗦一点,接口其实也有个关系在里面:
can-do关系:看一个接口的时候,主要看它能做什么。例如:一个类型能将自己的实例转换为另一个类型(IConvertible),用过Framework 提供的接口的同学,更能体会。
组合和继承是创建类的主要形式。
包含往往比继承更可取,除非你要对“is-a“关系建模。
继承是一种有用的工具,但它却会增加复杂度,复杂度是软件管理的首要杀手。
UML基本语法注解:
方法内"+"表示Public,“-”表示Private,还有一个“#”这里没有提到,表示Protected,它很少用到。
在方法后面,还有一些setName:void和getName:String只代表这个方法的返回类型。
括号内的就是参数列表。
这张图我们要关注的就是那个空心箭头,它表示继承。金毛猎犬继承于狗类。
这个就关注空心棱形。它表示组合,方向盘是汽车的一部分。
这个也简单。连接线就是代表关联,客户端和服务端就是关联的,再看一张前面介绍过的图:
虚线三角箭头代表继承自接口,而接口的描述方式就是箭头指向的样子interface。
使用UML来辅助设计非常有用,这里简单的介绍是为了让大家更能看懂设计模式的类图说明,UML的完整讲述就需要一本书了。
尽管UML重要,但学习OO技能更为重要,先学习OO的基础概念,才能看懂UML图。
图是辅助,辅助大脑更好的思考。
但这里提议的是:
无论你用什么例子,都应该把注意力放在OO概念上。
好了,基础就讲述这么多了,愿大家在设计模式的学的轻松^_^