设计模式总结 (转)

http://www.cnblogs.com/vrliym/articles/2287019.html

内含有各个设计模式的总结及详细说明的链接

 

Simple Factory Pattern(简单工厂模式)


  • 优势和缺陷

  在简单工厂模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面中摆脱出来,仅仅需要负责“消费”对象就可以了,而不必管这些对象究竟是如何创建以及如何组织的。这样就明确区分了各自的职责和权力,有利于整个软件体系结构的优化。

  不过,凡事有利就有弊,简单工厂模式的缺点也正体现在其工厂类上。由于工厂类集中了所有实例的创建逻辑,很容易违反GRASPR的高内聚的责任分配原则。将全部创建逻辑都集中到一个工厂类还有另外一个缺点,那就是当系统中的具体产品类不断增多时,可能会出现要求工厂类根据不同条件创建不同实例的需求。这种对条件的判断和对具体产品类的判断交错在一起,很难避免模块功能的蔓延,对系统的扩展和维护也非常不利。

  • 应用情景

  1. 工厂类负责创建的对象比较少。

  2. 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心。

  由于简单工厂很容易违反GRASP的高内聚责任分配原则,因此一般只在很简单的情况下应用。

 


Factory Method Pattern(工厂方法模式)


  • 优势和缺陷

  在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节。工厂方法模式的核心是一个抽象工厂类,各种具体工厂类通过抽象工厂类将工厂方法继承下来。如此使得客户可以只关心抽象产品和抽象工厂,完全不用理会返回的是哪一种具体产品,也不用关系它是如何被具体工厂创建的。

  1. 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。

  2. 使用工厂方法模式的另一个优点是在系统中加入新产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性非常好。优秀的面向对象设计鼓励使用封装(Encapsulation)和委托(Delegation)来构造软件系统,工厂方法模式正是使用了封装和委托的典型例子,其中封装是通过抽象工厂来体现的,而委托则是通过抽象工厂将创建对象的责任完成交给具体工厂来体现。

  3. 使用工厂方法模式的缺点是在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,当两者都比较简单时,系统会有相对额外的开销。

  • 应用情景

  1. 类不知道自己要创建哪一个对象。

  2. 类用它的子类来指定创建哪个对象。

  3. 客户需要清楚创建了哪一个对象。

 


Abstract Factory Pattern(抽象工厂模式)


  • 优势和缺陷

  抽象工厂模式的主要优点是隔离了具体类的生成,使得客户不需要知道什么被创建了。犹豫这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变这个软件的系统的行为。另外,应用抽象工厂模式符合GRASP纯虚构的模式,可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛应用。

  使用抽象工厂模式的最大好处是,当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是非常使用的一种设计模式。

  抽象工厂模式的确定是,在添加新的产品对象时,难易扩展抽象工厂以便生产新种类的产品。这是因为AbstractFatory接口规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对AbstractFatory及其所有子类的修改,显然有小小的不便,但不重要。

  • 应用情景

  1. 系统需要屏蔽有关对象如何创建、如何组织和如何表示。

  2. 系统需要由关联的多个对象来构成。

  3. 有关联的多个对象需要一起应用并且它们的约束是强迫的(不可分离)。

  4. 你想提供一组对象而不显示他们的实现过程,只显示它们的接口。

 


Builder Pattern(建造者模式)


  • 优势和缺陷

  建造者模式将一个复杂对象的生成责任作了很好的分配。它把构造过程放在指挥者的方法中,把装配过程放到具体建造者类中。建造者模式的产品之间都有共通点,但有时候,产品之间的差异性很大,这就需要借助工厂方法模式或抽象工厂模式。另外,如果产品的内部变化复杂,Builder的每一个子类都需要对应到不同的产品去做构建的动作、方法,这就需要定义很多个具体建造类来实现这种变化。

  • 应用情景

  1. 创建复杂对象的算法是独立于它的组成部件及装配过程。

  2. 构造的过程允许构造对象有不同的表现。

 


Prototype Pattern(原型模式)


  • 优势和缺陷

  原型模式得到了广泛的应用,特别是在创建对象成本较大的情况下(初始化需占用较长时间,占用太多CPU资源或网络资源。比如通过Webservice或DCOM创建对象,或者创建对象要装载大文件),系统如果需要重复利用,新的对象可以通过原型模式对已有对象的属性进行复制并稍作修改来取得。另外,如果系统要保存对象的状态而对象的状态变化很小,或者对象本身占内存不大的时候,也可以用原型模式配合备忘录模式来应用。相反地,如果对象的状态变化很大,或者对象占用内存很大,那么采用状态模式会比原型模式更好。原型模式的缺点是在实现深层复制时需要编写复杂的代码。

  • 应用情景

  1. 类的实例化是动态的。

  2. 你需要避免使用分层次的工厂类来创建分层次的对象。

  3. 类的实例对象只有一个或很少的几个组合状态。

 


Singleton Pattern(单例模式)


  • 优势和缺陷

  Singleton单例模式为一个面向对象的应用程序提供了对象唯一的访问点,不管它实现何种功能,此种模式都为设计及开发团队提供了共享的概念。然而,Singleton对象类派生子类就有很大的困难,只有在父类没有被实例化时才可以实现。值得注意的是,有些对象不可以做成Singleton,比如.net的数据库链接对象(Connection),整个应用程序同享一个Connection对象会出现连接池溢出错误。另外,.net提供了自动废物回收的技术,因此,如果实例化的对象长时间不被利用,系统会认为它是废物,自动消灭它并回收它的资源,下次利用时又会重新实例化,这种情况下应注意其状态的丢失。

  • 应用情景

  1. 系统只需要一个实例的对象。

  2. 客户调用类的单个实例只允许使用一个公共访问点。

 


Adapter Pattern(适配器模式)


  • 优势和缺陷

  适配器模式可以将一个类的接口和另一个类的接口匹配起来,使用的前提是你不能或不想修改原来的适配器母接口(adaptee)。例如,你向第三方购买了一些类、控件,但是没有源程序,这时,使用适配器模式,你可以统一对象访问接口。但客户调用可能需要变动。

  • 应用情景

  1. 对象需要利用现存的并且接口不兼容的类。

  2. 你需要创建可重用的类以协作其他接口不一定兼容的类。

  3. 你需要使用若干个现存的子类但又不想派生这些子类的每一个接口。

 


Bridge Pattern(桥接模式)


  • 优势和缺陷

  桥接模式可以从接口中分离实现功能,使得设计更具扩展性,这样,客户调用方法时根本不需要知道实现的细节。

  桥接模式减少了子类,假设程序要在2个操作系统中处理6种图像格式,纯粹的继承就需要(2*6)12个子类,而应用桥接模式,只需要(2+6)8个子类。它使得代码更清洁,生成的执行程序文件更小。  

  桥接模式的缺陷是抽象类与实现类的双向连接使得运行速度减慢。

  • 应用情景

  1. 你想避免抽象方法和其实现方法捆定在一起。

  2. 抽象接口和它的实现都需要扩展出子类以备使用。

  3. 变动实现的方法根本不会影响客户程序调用部分(甚至不用重新编译)。

 


Composite Pattern(组合模式)


  • 优势和缺陷

  组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新部件也更容易,因为它让客户忽略了层次的不同性,而它的结构又是动态的,提供了对象管理的灵活接口。组合模式对于树结构的控制有着神奇的功效,例如在人力资源系统的组织架构及ERP系统的BOM设计中,组合模式得到重点应用。

  组合模式的缺陷是使得设计变得更加抽象。对象的商业规则如果很复杂,则实现组合模式具有很大挑战性,并且,不是所有的方法都与叶部件子类有关联。

  • 应用情景

  1. 你想表示一个对象整体或部分层次。

  2. 你想让客户能够忽略不同对象的层次的变化。

  3. 对象的结构是动态的并且复杂层度不一样,但客户需要一致地处理它们。

 


Decorator Patten(装饰模式)


  • 优势和缺陷

  装饰模式提供了比静态继承更好的柔韧性,它允许开发一系列的功能类用来代替增加对象的行为,这既不会污染原来对象的源码,还能使代码更容易编写,使类更具扩展性,因为变化都是由新的装饰类来完成。还可以建立连接的装饰对象关系链。

  需要注意的是,装饰链不宜过长。装饰链太长会使系统花费较长时间用于初始化对象,同时信息在链中的传递也会浪费太多的时间。这个情况好比物品包装,包了一层又一层,大包套小包。另外,如果原来的对象接口发生变化,它所以的装饰类都要修改以匹配它的变化。派生子类会影响对象的内部,而一个Decorator只会影响对象的外表。

  • 应用情景

  1. 你想透明并且动态地给对象增加新的职责(方法),而不会影响其他对象。

  2. 你给对象增加的职责在未来会发生变化。

  3. 用子类扩展功能不实际的情况下。

 


Facade Pattern(外观模式)


  • 优势和缺陷

  外观模式提供了一个简单且公用的接口去处理复杂的子系统,并且没有减少子系统的功能。它遮蔽了子系统的复杂性,避免了客户与子系统直接链接,它也减少了子系统与子系统间的连接,每个子系统都有它的Facade模式,每个子系统采用Facade模式去访问其他子系统。外观模式的劣势就是限制了客户的自由,减少了可变性。

  • 应用情景

  1. 你需要复杂的子系统提供一个简单的接口。

  2. 客户与抽象的实现类中存在若干依赖。

  3. 子系统分层是必要的或架构要求的情况下。

 


Flyweight Pattern(轻量级模式)


  • 优势和缺陷

  Flyweight模式需要你认真考虑如何能细化对象,以减少处理的对象数量,从而减少存留对象在内存或其他存储设备中的占用量。然而,此模式需要维护大量对象的外部状态,如果外部状态的数据量大,传递、查找、计算这些恶数据会变得非常复杂。当外部和内部的状态很难分清时,不宜采用flyweight模式。

  • 应用情景

  1. 系统需要存在大量的对象而共享某些本质的、不变的信息。

  2. 对象可以同时用于多个环境下。

  3. 在每个实例下,flyweight可以作为一个独立的对象。

 


Proxy Pattern(代理模式)


  • 优势和缺陷

  当对象在远程机器上,要通过网络来生成时,速度可能会慢,此时应用Remote Proxy模式,可以掩蔽对象由网络生成的过程,系统的速度会加快;对于大图片的加载,Virtual Proxy模式可以让加载在后台进行,前台用的Proxy对象使得整体运行速度得到优化;Protect Proxy可以验证对真实对象的引用权限。

  代理模式的缺陷是请求的处理速度会变慢,并且实现Proxy模式需要额外的工作。

  • 应用情景

  1. Virtual Proxy(虚拟代理):Proxy不会生成一个真实的耗费代理,直到非常必要时(首次有请求)。它用来存放花费大(实例需要很长时间)的真实对象。

  2. Remote Proxy(远程代理):本地的代理对象控制一个远程的对象。

  3. Protection Proxy(安全代理):代理检查调用真实对象所需要的权限。

  4. Smart Reference(聪明引用):当调用真实的对象时,代理处理另外一些事。

 


Chain of Responsibility(责任链模式)


  • 优势和缺陷

  责任链模式可以减少对象的连接,为对象责任分配增加了很大的灵活性。该模式允许把一组类作为一个类来使用,并且在类的组合中,一个类的事件可以发送到另一个类并由其处理。

  责任链模式通常应用与图形用户界面中,窗体的部件可能会包含其他几个小部件,就如同Windows窗体应用程序中,控件中又可以放置其他控件,控件边界会决定是否处理事件,或者将事件传递给父控件来处理。

  另外,责任链还会以树状出现,这样,一个事件可以传给多个类,或者,多个类的信息可以提交到一个类。树状责任链能够提供更灵活的技巧,但缺点是信息在树中容易迷失。

  • 应用情景

  1. 超过一个对象能够处理客户请求并且到底哪个对象处理预先不知道。

  2. 一个请求可以发布到多个对象但它的接收都是不清晰。

  3. 可以动态指定一组对象处理请求。

 


Command Pattern(命令模式)


  • 优势和缺陷

  命令模式分离了接受请求的对象与实现处理请求工作的对象,这样,已经存在的类可以保持不变,使得增加新类的工作更简单。例如,很多软件的宏命令就提高了系统的自动化程度。

  命令模式还可以分离用户界面和业务对象,降低系统的耦合度。

  但是,命令模式最主要的缺陷就是,类的数量增加了,系统变得更复杂,程序的调试工作也相应变得困难。

  • 应用情景

  1. 当你需要与工作相关的对象来作为参数。

  2. 你需要在不同的时间创建请求,生成请求队列,执行请求。

  3. 你需要支持取消、保存修改日志或处理事务功能。

  4. 你需要支持宏命令。

 


Interpreter Pattern(解释器模式)


  • 优势和缺陷

  解释器模式的作用很强大,它使得改变和扩展文法变得容易,实现文法也变得简单明了,很多编译器,包括文本编辑器、网页浏览器及VRML都应用解释器模式。

  解释器模式的缺陷就是,因为文句会分析成树结构,解释器需要递归访问它,所以效率会受影响。这种情况开发人员会有所体会,编译整个工程源码耗费时间都比较长。

  • 应用情景

  1.语言的文法需要扩展。

  2.程序效率不太重要。

 


Iterator Pattern(迭代器模式)


  • 优势和缺陷

  迭代器模式支持在聚集中移动游标,使得访问聚合中的元素变得简单,简化了聚集的接口,封装了聚合的对象。

  迭代器模式还可以应用于对树结构的访问,程序不需要从头逐行代码查找相应位置,可控制到从子集开始查找,对于加快程序的运行速度有很重要的作用。

  迭代器模式的缺点是聚合密切相关,增加了耦合。但将这种耦合定义在抽象基类,可解决这个问题。

  • 应用情景

  1.需要遍历访问聚集中的对象而不能暴露聚集的内部结构。

  2.允许对聚集的多级遍历访问而不会相互受影响。

  3.提供一个一致的接口来遍历聚集中不同的结构。

 


Mediator Pattern(中介者模式)


  • 优势和缺陷

  中介者模式分离了两个同事类,简化了对象协议,中央控制对象交互,从而使个体对象变得更容易且更简单,因为它不需要传递数据给其他个体对象,仅仅传给中介者就可以了。个体对象不需要具有处理内部交流的逻辑,所以更加突出它的面向对象特性。

  • 应用情景

  1.一组对象复杂地互相通信但其方法是定义明确的。

  2.若干个对象需要定义方法又不需要子类实现。

  中介者模式通常用在基于信息通信的系统结构中。这种信息传递到关联的对象,其自身不直接链接。

 


Memento Pattern(备忘录模式)


  • 优势和缺陷

  Memento模式保存了封装的边界,一个Memento对象是另一种原发器对象的表示,不会被其他代码改动。这种模式简化了原发器对象,Memento只保存原发器的状态。采用堆栈备忘对象,可以实现多次取消操作。

  • 应用情景

  1.对象状态的备忘足以使对象可以完全恢复到原来的状态。

  2.使用一个直接的接口来取得状态会使实现细节过程化,这样会打破对象的封装性。

 


Observer Pattern(观察者模式)


  • 优势和缺陷

  观察者模式抽象了被观察对象与观察者对象的连接,提供了广播式的对象间通信,并且容易增加新的观察者对象。观察者模式的缺陷是对象间的关系难以理解,在某种情况下会表现低效能。

  • 应用情景

  1.对一个对象的变化请求需要其他对象也变化,并且其他要变化对象的数量不明确。

  2.一个对象需要通知其他对象而不需要掌握其他对象的识别方法。

 


State Pattern(状态模式)


  • 优势和缺陷

  状态模式在对象内保存特定的状态并且就不同的状态履行不同的行为,它使状态的变化显得清晰明了,也很容易创建对象的新状态。

  状态模式在工作流或游戏等各种系统中大量使用,例如在政府OA系统中,一个批文的状态有多种:未办、正在处理、正在批示、正在审核和已经完成等各种状态。在网络游戏中,一个游戏活动存在开始、开玩、正在玩、输赢等各种状态。使用状态模式就可以实现游戏状态的总控,而游戏状态决定了游戏的各个方面。

  • 应用情景

  1.对象的行为依赖于它的状态并且它必须可以根据它的状态而改变它的行为。

  2.操作很多部分都带有与对象状态有关的大量条件语句。

 


Strategy Pattern(策略模式)


  • 优势和缺陷

  策略模式提供了替代派生的子类,并定义类的每个行为,剔除了代码中条件的判断语句,使得扩展和结合新的行为变得更容易,根本不需要变动应用程序。策略模式可以避免使用多重条件转移语句,系统变得更新灵活。应用策略模式会产生很多子类,这符合高内聚的责任分配模式。

  • 应用情景

  1.多个类的分别只是在于行为不同。

  2.你需要对行为的算法作很多变动。

  3.客户不知道算法要使用的数据。

 


Template Method Pattern(模版方法模式)


  • 优势和缺陷

  模版方法模式在一个类中形式化地定义算法,而由它的子类实现细节的处理。模版方法模式的优势是,在子类定义处理算法时不会改变算法的结构。

  模版方法的特点在于,每个不同的实现都需要定义一个子类,这也复合高内聚的责任分配模式,不能说成是它的缺点。

  • 应用情景

  1.你想将相同的算法放在一个类中,将算法变化的部分放在子类中实现。

  2.子类公共的算法应该放在一个公共的类中,避免代码重复。

 


Visitor Pattern(访问者模式)


  • 优势和缺陷

  Visitor(访问者)模式使得增加新的操作变得容易,它可以收集有关联的方法,而分离没有关联的方法,特别适用于分离因为不同原因而变化的事物,如“在男人中分离出男孩”。但Visitor模式常常要打破对象的封装性,visitor与element需要达成某些共识。

  • 应用情景

  1.一个对象的结构包含多个不同接口的对象,而且需要根据具体对象作不同的处理。

  2.对结构中的对象有很多不同且没有联系的处理,因此需要避免操作将类分离。

  3.类中定义的对象结构很少改变,但你需要经常地定义处理结构的新操作。

posted @ 2012-10-21 21:34  小心小意  阅读(154)  评论(0编辑  收藏  举报