深入浅出设计模式基础(一):总结&概述
小引
最近在读<<大话设计模式>>,也刚好自己的本科毕业设计是有关设计模式的内容,所以把本书的大概的内容通读了一遍,希望在本书当作自己初认识设计模式的开始阶段,想必大家都听说宫保鸡丁如何制作吧,他是经过不断实践、思考、总结,最后得到最佳的烹饪方法,而程序设计也如此,有方法,程序不是有生俱来的,也不是一种发明,他是利用前人的经验,使解决问题不需要从头解决,设计模式也由此而生了,使得程序重用性和可维护性提高
主要内容:
- 设计模式概述
- 设计模式分类
- 设计模式作用
- 可重用性
- 简单工厂模式
- 策略模式
- 单一职责原则
- 开放-封闭原则
- 依赖倒转原则
- 装饰模式
- 代理模式
- 工厂方法模式
- 原型模式
- 模板方法模式
- 迪米特法则
- 外观模式
设计模式概述
设计模式通常是对于某一类软件设计问题的可重用的解决方案,将设计模式引入软件设计和开发过程,其目的在于要充分利用已有的软件开发经验,优秀的软件设计师都知道,不是每个问题都有从头开始解决,而是复用以前曾经使用过的解决方案,每当找到一个好的方案了,就一遍一遍在使用,熟练了,设计模式的目标就是帮助人们利用成功软件的集体开放经验,做出更加好的解决产品。
1、Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
2、Adapter:将一个类的接口转换成客户希望的另外一个接口。A d a p t e r模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
3、Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
4、Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
5、Chain of Responsibility:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
6、Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
7、Composite:将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。
8、Decorator:动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。
9、Facade:为子系统中的一组接口提供一个一致的界面, F a c a d e模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
10、Factory Method:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
11、Flyweight:运用共享技术有效地支持大量细粒度的对象。
12、Interpreter:给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
13、Iterator:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
14、Mediator:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
15、Memento:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
16、Observer:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
17、Prototype:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
18、Proxy:为其他对象提供一个代理以控制对这个对象的访问。
19、Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
20、State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
21、Strategy:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
22、Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
23、Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
设计模式分类
1、目的划分
创建型(Creational):与对象创建有关
结构行(Structural):处理类和对象的组合
行为型(Behavioral):描述类或者对象如何交互和如何分配职责
2、范围划分
类模式:用于处理类和子类的关系,这些关系通过继承建立,是静态的,在编译的就已经确定下来了,当然几乎所有的模式都是使用继承机制,所以这里的“类模式”是指处理类间关系的模式
对象模式:用于处理对象间的关系,这些关系具有动态性,在运行的时候是可以变化的
范围\的 创建型(Creational) 结构行(Structural): 行为型(Behavioral) |
类 Simple Factory Adapter (CLASS) Interpereter Factory Method Template method 对象 Abstract Factory Adapter(OBJECT) Chain of Responsibility Builder Bridge Command Prototype Composite Iterator Singleton Decorator Meditor Facade Memento Flyweight Observer |
设计模式的作用
1、重用设计,自动带来代码重用
2、为设计代码共同的词汇,每个模式就是一个设计词汇,使交流更加方便
3、在开发文档的采用模式词汇可以容易理解你的想法,理解为什么这样子做,你多了些什么,使开发文档更加容易
4、可以使重构系统变得容易,可以确保开发正确的代码,并降低在设计或者实现当中出现错误的可能,同时可以重写其他应用程序提供更好的系统框架
5、正确使用设计模式可以节省大量时间
可重用性
•传统的可重用性:包括代码复制粘贴;算法重用,如:排序算法等;数据结构重用 如:队列、数组等
- 面向对象:可维护、可复用、可扩展、灵活性好
- 业务封装:业务逻辑与界面逻辑分开,让它们的耦合 度下降
- 面向对象三大特性:封装,继承,多态
- URL类图:注意前面的符号,“+”表示public,“-”表示 private,“#”表示protected
- 继承、接口、关联、聚合、合成(组合)、依赖
- 简单工厂模式可以解决对象的创建问题
策略模式
- 策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互 相替换,此模式让算法的变化不会影 响到算法的客户。
- 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工 作,只是实现不同,它可以以相同的 方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
- 策 略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。
- 策 略模式的优点是简化了单元测试, 因为每个算法都有自己的类,可以通过自己的接口单独测试。
- 当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。 将这些行为封装在一个个独立的Strategy类中,可以在使用这些行为的类中消除条件语句。
- 策 略模式就是用来封装算法的, 选择所用具体实现的 职责由客户端对象承 担,并转给策 略模式的Context对 象。
单一职责原则
- 单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。
- 如 果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职能的能力。这种耦合会导致脆弱的设计,当变化发 生时,设计会遭受到意想不到的破坏。
- 软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。
- 如 果你能够想到多于一个的动机去改变一个类,那么这个类就具 有多于一个的 职责。
开放-封闭原则
- 开放-封闭原则:就是说软件实体(类、模 块、函数等等)应该可以扩展, 但是不可修改。 两个特征,对于扩展是开放的, 对于更改是封闭的。
- 怎 样的设计才能面对需求的改变却可以 保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本呢?
- 设计的时候,尽量让这个类足够好, 写好了就不要去修改了,如果新需求来,我们增加一些类就完事了,原来的代码能不动则不动。
- 无论模块多么的“封闭”,都会存在一些 无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。
- 在 我们最初编写代码时,假设变化不会发生。当变化发生时,我们就创建抽象来隔离以后发生的同类变化。
- 面对需求,对程序的改动是通 过增加新代码进 行的,而不是更改现有的代码。
依赖倒转原则
- 依赖倒转原则:抽象不应该依赖细节,细节应该依赖于抽象;针对接口编程,不要对实现编程。A. 高层模块不应该依赖低层模块。两个都应该依赖抽象。B. 抽象不应该依赖细节。细节应该依赖 抽象。
- 里氏替换原则:子类型必须能够替换掉它们的父类型。
- 只 有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
- 由 于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展。
- 依赖倒转其实可以说是面向对象设计的标志,如果编写时考虑的都是 如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之就是过程化的设计了。
装饰模式
- 动态地给一个对象添加一些额外的职责,就增加功能来说, 装饰模式比生成子类更为灵活。
- 装饰模式是利用SetComponent来对对象进行包装的。
- 每 个装饰对象的实现就 和如何使用这个对象分 离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。
- 装饰模式是为已有功能动态地添加更多功能的一种方式。
- 当 系统需要新功能的时候,是向旧的类 中添加新的代码,在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度;而装饰模 式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因为, 当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择的、按顺序地使用装饰功能包装对象了。
- 优点:把类中的装饰功能从类中 搬移去除,这样可以简化原有的类; 有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
代理模式
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
- 应 用场合:第一、远程代理, 也就是为了一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实(调用WebService); 第二、虚拟代理, 是根据需要创建开销很大的对象。通过它来存放实例化需要很长的时间的真实对象(浏览网页,文字先下,图片后下,使用代理);第三、安全代理,用来控制真实对象 访问时的权限; 第四、智能指引, 是指当调用真实的对象时,代理处理 另外一些事。
- 代理就是真实对象的代表。
工厂方法模式
- 简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的 选择条件动态实例化相 关的类,对于客户端来说,去除了与具体产品中的依赖。
- 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工 厂方法使一个类的实例化延迟到其子 类。
- 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就 是说,工厂方法把简单工厂的内部逻 辑判断移到了客户端代码来进行。你想要加功能,本来是改工厂类,而现在是修改客户端。
原型模式
- 原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
- 原 型模式其实就是从一个对象再创建另 外一个可定制的对象,而且不需知道任何创建的细节。
- 一般在初始化的信息不发生变化的情况 下,克隆是 最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高。
- MemberwiseClone()方法是这样,如果字段是值类型的,则对该字段 执行逐位复制, 如果字段是引用类型, 则复制引用但 不复制引用的对象;因此,原始对象 及其复本引用同一对象。
- “浅复制”,被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的 引用都仍然指向原来的对象,所以我们需要把要复制的对象所引用的对象都复制一遍,这种方式就是“深复制”,深复制把引用对象的 变量指向复制过的新对象,而不是原有的被引用的对象。
模版方法模式
- 我 们既然用了继承,并且肯定这个继承有 意思,就应该要成为子类的模板, 所有重复的代码都 应该要上升到父类去, 而不是让每个子类都去重复。
- 当 我们要完成在某一细节层次一致的 一个过程或一系列步骤,但其个别步 骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法模式来处理。
- 模板方法模式:定义一个操作中的算法 的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算 法的结构即可重定义该算法的某些特定步骤。
- 模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现 它的优势。
- 模板方法模式就是提供了一个很好的代码复用平台。
- 当不变的和可变的行为在方法的子类实现中混合在一起的时候, 不变的行为就会在子类中重复出现。我们通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。
迪米特法则
- 迪米特法则也叫最少知识原则:如果两个类不必 彼此直接通信,那么这两个类就不应当发生直接的交互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
- 首 先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。
- 迪米特法则其根本思想,是强调了类之间的松耦合。
- 类 之间的耦合越弱,越有利于复用,一个处在弱耦 合的类被修改,不会对有关系的类造 成波及。
- 信息的隐藏促进了软件的复用。
外观模式
- 外 观模式:为子系统的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这子系统更加容易使用
- 首先,在设计的时候,应该有意识低将不同的两个层分离,比如三层架构,就需要在数据访问层的和业务逻辑层,表现层的层与层之间建立外观的Facade
- 其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观Facade可以提供一个简单的接口,减少他们之间的依赖
- 最后,维护一个遗留的大型系统时,可能这个系统已非常难以维护和扩展,你可以用外观模式,当然你在为新系统开发一个外观Facade类,来提供设计粗糙或者高度复杂的遗留代码的比较清闲简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作
后记
本文虽然没有详细介绍各种具体的设计模型,而是总结大话设计模式当中的结论性的语句,但是在各个大标题下也总结了与具体设计模式类似的方法,往后有时间在详细介绍常见的设计模式! 主要参考:
C# 23种设计模式汇总:http://bbs.51aspx.com/showtopic-43429.html
大话设计模式
深入浅出设计模式
作者:类菌体
出处:http://www.cnblogs.com/bacteroid/archive/2012/03/21/2410704.html
关于作者:在校学生
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接
如有问题,可以通过303323670@qq.com 联系我,非常感谢。