1. 什么是设计模式
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。简单说:
模式:在某些场景下,针对某类问题的某种通用的解决方案。
场景:项目所在的环境
问题:约束条件,项目目标等
解决方案:通用、可复用的设计,解决约束达到目标。
2.设计模式的三个分类
创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
结构型模式:把类或对象结合在一起形成一个更大的结构。
行为型模式:类和对象如何交互,及划分责任和算法。
如下图所示:
3.各分类中模式的关键点
- 单例模式:某个类只能有一个实例,提供一个全局访问点。
- 简单工厂:一个工厂根据传入参数决定创建哪一种产品类的实例。
- 工厂方法:定义一个创建对象的接口,让子类决定实例化哪个类。
- 抽象工厂:创建相关对象或依赖的加载,无需指明具体类,。
- 建造者模式:封装一个复杂对象的建造过程,并可以按步骤构造。
- 原型模式:通过现有的实例来创建新的实例。
- 适配器模式:将一个类的方法接口转换成客户希望的另一个接口。
- 组合模式:将对象组装成树形结构以表示“部分-整体”的层次结构。
- 装饰模式:动态的给对象添加新的功能。
- 享元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。
- 外观模式:将抽象部分和他的实现部分分离,使它们可以独立地变化。
- 模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
- 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
- 策略模式:定义一系列算法并把它们封装起来,并且是他们可以相互替换。
- 状态模式:允许一个对象内部状态改变时改变他的行为.
- 观察者模式:对象间的一对多的依赖关系。
- 备忘录模式:在不破坏封装的前提下,保持对象内部的状态,
- 中介者模式:用一个中介对象来封装以一系列的对象交互。
- 命令模式:将命令封装成一个对象,使得可以用不同的请求来进行参数化。
- 访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
- 责任链模式:将请求和发送者和接收者解耦,使得多个对象都有处理这个请求的机会。
- 迭代器模式:一种遍历访问各个元素的方法,不暴露该对象的内部结构。
如何学习设计模式
① 学习技巧
学习设计模式时,有一些技巧能够帮助你快速理解设计模式。
a) 使用较简单的面向对象的语言如Java、C#。GoF的[设计模式]实质上是面向对象的设计模式。[GoF·1.1]中提到“程序设计语言的选择非常重要,它将影响人们理解问题的出发点”。从学习设计模式的角度看,Java和C#较C++更容易一些。比如Java接口等,能够更有效展现设计模式的意图。
b) 使用工具BlueJ。BlueJ最大的好处,就是提供了简单的类图。正如我在简明设计模式Java中所做的,较少去专门画类图,而是在BlueJ中截图。在学生上机编写演示程序时,常常先看他的类图,以判断他的程序是否正确,必要时再看源代码。
c) 日常生活的隐喻。用一些实际生活中的例子来说明某某模式,能够让你快速掌握某模式的目的和实现代码的结构。同时,你要认识到,这种隐喻如同告诉你(2+3)2=22+223+32,你需要自己举一反三,得出(a+b)2=a2+2ab+b2。在实际工作中的模式的具体应用,则相当于应用代数公式。
d) 动手实践和怀疑精神。看显浅的参考书或上网查阅资料时,要自己敲(复制也可以)代码并运行,要多修改别人的源代码提出自己的观点:为什么书中不这样设计、为什么要那样设计;如果增添一些方法、方法参数、或成员变量会如何?必须要自己亲自动手,最起码要运行。另外,要敢于向博主提问、拍砖。你甚至可以质疑GoF的某些章节的解说和意图,更何况一些博主呢。
② 基础知识
这些知识让你知道,设计模式好在何处。
a) 面向对象范式。也就是人们传说的思想。封装、继承和多态这些东西,在我看来比if、for等稍微高一点,也属于语法问题。面向对象编程要掌握的三大原则是柏拉图(Plato)原则、里氏(Liskov)替换原则和Parnas原则。这三个原则其实非常简单。任何原则,你觉得很难一见钟情,很难快速认同,那它就不会是好原则。
b) 设计原则。许多人列举了7大原则,如单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则。LSP,我将它提升为面向对象范式的3大基石之一;单一职责和接口隔离,主要作为面向对象分析/OOA时职责划分所遵循的原则,此时你可以不太在意。依赖倒转原则,我把它作为垃圾扔掉,因为开闭原则或者直接地说“依赖于抽象类型原则”已经包含了依赖倒转原则的精华,而依赖倒转原则的糟粕由IoC继承。当然,回调,我很强调。所以,你要掌握的有抽象依赖原则(OCP)、单向依赖原则(含对回调的学习)和最低依赖原则(合成复用原则、迪米特法则)。
c) UML的初步了解。这是学习设计模式的工具。在早期,你甚至可以仅了解BlueJ的相关图示,也就10分钟的事情。
③ 境界
《五灯会元》卷十七中,有一则唐朝禅师青原惟信禅师的语录:“老僧三十年前未参禅时,见山是山,见水是水。及至后来亲见知识,有个入处,见山不是山,见水不是水。而今得个休歇处,依前见山只是山,见水只是水。”
a) 仔细研究GoF的[设计模式],逐个学习其意图和结构,是一个抱着字典学习英语的方式。见山是山,见水是水,导致你可能在实际工作中生搬硬套、东施效颦。
b) 建议从简单的场景出发,自己发现或设计出某种模式。你从中体会该模式是如何解决问题的,这样,该模式成为你自己的东西,你才不会出现知易行难的问题。所有的设计模式不过是基本原则和理念在特定场合的应用。你可能不知道某个设计模式的名字,但是你知道它一切的优缺点和变体以及应用场合。见山不是山,见水不是水。
c) 你对基本原则和理念融会贯通,你可以惋惜:“我找到一种模式,原来在设计模式中早就有了这种模式”。这时,模式不模式又如何呢?反模式又怎样。看见一个模式,你会说:“嗯,这是一种有用的模式”。见山只是山,见水只是水。
以上一点浅见。
注:【】中的内容是我加的。
1 转录【IT168知识库】
发现很多初学设计模式的人都有一些特点就是学习了某个设计模式之后,貌似理解了,但是却不知道怎么去使用这些所谓的精华经验,苦于不知如何下手。我最初学习设计模式的时候也有类似的经验,我将我的经验分享出来,希望能对初学者有帮助。
我对设计模式产生兴趣是在大概一年以前,最初看书的时候好像是看懂了,大概知道他在说什么。看了几个模式之后就开始寻找时机来套用套用这些模式。结果是除了Singleton模式以外的其他模式都没有找到应用的场所。然后我就没开始看下去了,我知道再看也没用,但是我并没有放弃对设计模式的关注。
不久我就在MSDN的Webcast上看到李建忠的 C#面向对象设计模式纵横谈讲座,很不错的系列讲座,让我对设计模式有了新的理解。我意识到学习设计模式,确切的讲是学习面向对象的设计模式,应该从学习面向对象开始。【面向对象的原理如同了解下象棋的规则,而设计模式相当于残局,不知道规则看什么残局】由于之前一年都在做asp.net开发,虽然都是在写类、学着duwamish搞分层架构、搞类型化DataSet、也弄过自定义实体类,但好像一年下来还没怎么用过接口,什么多态也是极少用。事实上对面向对象的编程思想的认识还是很模糊的。
重新认识OO:面向对象编程是一种思想,以面向对象的思维来思考软件设计结构,从而强化面向对象的编程范式。面向对象的特点是封装,继承,多态【这些也算?】。所以从那是开始,当我设计一个类的时候,不断的提示自己以下三点:
第一:别把自己的数据公开,除非你要向别人提供数据,使用尽量低的访问权限。
第二:以一个外部的视角来看类,紧记不要要求别人要在知道你是怎么实现一个方法之后才能使用我的类。
第三:分清类的职责,该这个类做的事情就要在这个类中实现,不该我的类做的事情就让别的类去实现。
在这三点的指导下来写类,写程序开始像在做“设计”了_。
一段时间后对设计模式就慢慢有感觉了,并能够找到一些设计模式的应用场景了。并常套用套用那些模式,逐渐的加深对模式的理解,并把它变成自己的东西,能够在其他的地方灵活的用起来。
- 转录 《易学设计模式·1.4 如何学习设计模式》郭志学 人民邮电出版社
如何学习设计模式
在了解了设计模式的历史和分类后,应该如何学习设计模式呢?在学习设计模式之前,读者一定要树立一种意识,那就是:设计模式并不只是一种方法和技术,它更是一种思想、一个方法论。它和具体的语言没有关系,学习设计模式最主要的目的就是要建立面向对象的思想,尽可能地面向接口编程、低耦合、高内聚,使你设计的程序尽可能地复用。【似是而非。学习设计模式能够更好理解面向对象的思想,设计模式是一些设计的技巧和窍门,不要上升到思想、方法论好不好】
有些软件开发人员,在程序设计时,总想着往某个设计模式上套,其实这样是不对的,并没有真正掌握设计模式的思想。其实很多时候读者用了某种设计模式,只是自己不知道这个模式叫什么名字而已。因此,在程序设计时,要根据自己的理解,使用合适的设计模式。
而有另外一些软件开发人员,在程序设计时,动不动就给类起个类似模式的名字,比如叫某某Facade、某某Factory等,其实类里面的内容和设计模式根本没有一点关系,只是用来标榜自己懂设计模式而已。
因此,学习设计模式,首先要了解有哪些方面的设计模式可以供开发人员使用,然后再分别研究每个设计模式的原理,使用时机和方法,也就是说要在什么情况下才使用某个设计模式,在了解某个设计模式的使用时机时,还要了解此时如果不使用这个设计模式,会造成什么样的后果。当对每个模式的原理和使用方法都了解了以后,更重要的是,学习面向对象的思想方式,在掌握面向对象的思想方式后,再回过头来看设计模式,就会有更深刻的理解,最后,学习设计模式,一定要勤学多练。【就最后一句很赞同】
个人感悟
学习设计模式确实有几种境界:
第一种是学习了一两个设计模式,就一直想用到自己的代码中去;
第二种是学完全部设计模式,觉得很多模式都很相似,分不清楚它们之间有什么区别;
第三种是灵活运用设计模式,就算不用具体哪种模式也可以设计也高质量的代码,无剑胜有剑。