设计模式前言

前言

使用面向对象语言进行软件开发的人,对设计模式都应该有一定的情结,或多或少都接触过或者听说过若干种设计模式,比如常见的工厂模式、单例模式、模板方法等。当然,也有很多人天天和这些常用的设计模式打交道,只是因为没有系统地学习过相应设计模式,不知其理其形,所以纵使天天与其“照面”,也不相识。想来自己现在也对面向对象思想有了一定程度的理解,是时候系统地学习和整理下自己平时所熟识的种种设计模式呢。当然在园子里已经很多大牛已经写过很详细很通俗易懂的设计模式系列文章呢,自己重新再写一次,想必也不太可能总结得比大牛们还要好,但是本着学习、记录与交流的宗旨,还是大胆地将自己对设计模式的学习和理解诉诸博客中吧。所谓艺高人胆大,如果有什么错误或者欠考虑的地方,还恳请各位同志们大方指出,共同进步吧!

设计模式

地上本没有路,走得人多了也就成了路。设计模式同样遵从此理。设计模式不是规则、不是体系,更多的是经验的传承。既然说是经验的传承,自然,设计模式就不能说是被人为创造出来的,只能说是被人发现、归纳、总结出来的而已。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。那么究竟什么才是设计模式呢?这个问题没有标准答案。

设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

在我自己理解看来,设计模式应该是介于代码与架构之间一个东西,也是联系两者最重要的一个纽带,起到承上启下的作用。模式可以指导代码的编写,而架构亦可以利用模式进行局部的设计。很多人把设计模式与架构相混淆,其实很不应该。从宏观上来说,设计模式只是架构的一部分,从微观上来说,设计模式只是架构各部分实现的方式。构架更加关注的是所谓的High-Level Design,而模式关注的重点应该通过经验提取的“准则或者是指导方案”在设计中的使用,在不同层面上考虑问题的时候就形成了不同问题域上的模式。模式的目标是把共通部分中的不变的和变化的部分分隔出来,而不变的部分就是我们所说的模式【TerryLee】。一个好的架构当然离不开各种模式合理灵活的运用,因为应用设计模式终将会使整个系统架构或者说软件拥有面向对象技术所声称的巨大好处,即可维护、可扩展、可复用、灵活性好。

Christopher Alexamder说过:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。尽量Alexander说的是建筑学上的模式,但是其实这种思想与面向对象设计模式如出一辙。软件设计中存在诸多“内力”,作为软件设计者应该尽量疏导系统中的各种内力,使系统趋于稳定,有生气。一切软件设计都应该从此出发。变化是软件的永恒之道,开发者应该拥抱变化,利用变化,而不应该逃避变化。好的软件只能“产生”,而不能创造,我们只能利用相对较好的方法,让软件朝好的方向发展。

不可否认的是,在这个世界上,有那么一些天才程序员可以在一段代码程序中同时使用六种设计模式,也可以不用任何一种设计模式而把代码设计得很好。但是我们追求的是有效的设计,通过学习、理解、使用已有的各种设计模式可以为我们更好地实现这个目标。

在实际的开发中,我们不需要视设计模式为圭臬,正确、合理、适当地使用模式才是我们明智的做法。相信很多人都或多或少地看过GOF《设计模式》,甚至对其中所讲的23种设计模式已经背得滚瓜乱熟呢,但是真正对各种模式在适用场景、优缺点以及模式间彼此关联区别的认识却远远还没有在自己脑海里形成深刻的认识,以致真正在实际的开发过程中,不能很好地学以致用。学好设计模式的关键还是在于你付诸实践的使用和练习以及对其的深刻思考,只有做到当遇到适合使用某种模式的特定场景时,能够条件反射般地对其信手拈来,那就算是真正对模式达到融会贯通的地步呢。自然,想达到这样一种境界,需要长时间的练习和思考,绝非一朝一夕就能完成。其实即使是很有经验的程序员,也不敢夸口对各种设计模式都能合理使用,顶多是对其中部分设计模式有了较深刻的理解而已。因此,对于我们这些菜鸟程序员来说,完全没有必要自卑,只要踏实系统地学习、理解、实践,相信有朝一日,我们定能较好地合理使用各种模式,同时熟知其优缺点及适合场景,使我们的设计水平更上一层楼。

UML简介

既然说到面向对象,自然就不得不提到UML(统一建模语言)呢。通过UML可以很方便清楚地表达出面向对象设计中的需求,行为、体系结构的实现。在后续的系列设计模式文章中都会使用到UML图来展现各种模式的结构,因此,在真正进入介绍模式之前,我们先在这里大概地讲述下UML模式中各种图形图案在OOP中所对应的概念。在这里,我借用《大话设计模式》一书中的UML类图示例:

clipboard

接下来,我们就针对上图中的若干符号意义进行说明。

  1. +:表示public
  2. -:表示private
  3. #:表示protected
  4. 关联关系:当一个类需要“知道”另一个类时,比如上图中企鹅需要知道气候的变化,可以用关联规则,用实线箭头来表示
  5. 依赖关系:当一个类依赖于另一个类时,比如上图中的动物依赖于氧气和水,可以用依赖关系,用虚线箭头来表示
  6. 聚合关系:聚合表示的是一种弱的“拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分,使用空心的菱形+实线箭头来表示
  7. 合成关系:合成表示的是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期是一样的,使用实心的菱形+实线箭头来表示
  8. 继承关系:子类继承父类操作及属性,通过实线+实心三角形表示
  9. 实现关系:实现某一接口,通过虚线+实心三角形表示

有了上述对UML以及各种图形图案意义的讲述,相信在之后的UML图示表示中,大家应该不会有太多的疑问和不解呢。当然UML功能很多,这里,我只是挑选出在本系列文章需要使用到的UML知识点而已,并不打算全方位地来介绍UML。

面向对象原则

在面向对象设计中,有很多前人总结出来的各种原则(或法则)。在设计的过程中,尽量遵循以下原则,那么相信软件的设计也就会更加规范化,标准化,自然也就更加健壮化!在后续介绍的各种模式,几乎都遵循以下原则中的若干点,因为模式本来就是经验的传承嘛,详细介绍会在之后的文章中讲述,敬请期待!

  1. 单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因。
  2. 开放—封闭原则:是说软件实体(类、模块、函数等等)应该可以扩展,但是不可以修改。
  3. 依赖倒置原则:A.高层模块不应该依赖低层模块,两个都应该依赖抽象 B.抽象不应依赖细节。细节应该依赖抽象。
  4. 里氏代换原则(LSP):子类型必须能够替换掉它们的父类型。
  5. 迪米特法则(LoD):如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中有一个类需要调用另一个类的某一个方法的各方面,可以通过第三者转发这个调用 。迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。其根本思想是强调了类之间的松耦合。

结束语

其实,学习设计模式并不难,难得是一颗坚定、持久的心。上面的很多话语都是摘抄于自己以前浏览看到过的博客及书籍中,在这里就不一一给出说明呢!既然已经迈出了学习模式的第一步,希望大家能和我一道坚持把所有23种设计学习吃透吧!大家的支持是自己持续写作的最大动力!请关注本系列文章的下一篇!

 

 

posted @ 2012-09-14 09:41  JackyBing  阅读(967)  评论(6编辑  收藏  举报