DESIGN PATTERNS学习笔记

*相关模式及比较
 
 
1.创建型模式
 
ABSTRACT FACTROY(抽象工厂)
抽象工厂主要应用于系统有多个产品且系统与其产品之间存在独立性时。
抽象工厂可以一次性地创建一个系列中的多个产品,且这些产品可以在一起使用。
任何一个产品系列事实上只需要一个工厂就可生产,因此工厂可以被设计为单件。
对外界观察者,抽象工厂提供了一个统一的接口,外界不需要知道它的具体实现是怎样的。
对每一个产品系列都要实现一个具体的工厂类,这样当存在多个产品系列的时候,将存在同样多的工厂实现。
* ABSTRACT FACTORY 通常使用FACTORY METHOD模式实现,也可能使用PROTOTYPE模式实现,一个具体的FACTORY通常表现为SINGLETON形式。
 
BUILDER(生成器)
生成器主要应用于复杂对象创建过程,该对象的构造算法独立于对象的组成部分和装配方式。
生成器所构造的对象在系统中应该会出现不同的表示/表现/外观。
生成器的应用使产品的内部改变不会影响其外观,但当产品内部产生改变时,生成器也应随之变化。
对象生命周期分创建过程、应用过程和消亡过程,生成器封装了它的创建过程,特别是对复杂对象的创建过程的封装使外界不必关心对象是如何创建的。
生成器适合于一个有多个步骤的创建过程,它可以控制过程中的每一个步骤,也因此可以更有效地控制一个复杂对象的内部结构。
* BUILDER和ABSTRACT FACTORY很相似,但BUILDER侧重于一个对象的创建步骤的控制,而ABSTRACT FACTORY则侧重于创建一个对象系列。BUILDER有多个步骤,最后一个步骤完成时才真正地产生产品,而ABSTRACT FACTORY则一般只有一个步骤,该步骤完成后就可产生产品。
 
FACTORY METHOD(工厂方法)
FACTORY METHOD的存在是因为工厂类并不知道它所不要创建的类是什么或者希望由它的子类而非其本身来创建结果对象时。
工厂可以是一个仅提供工厂接口的抽象类,也可以是一个提供了缺省实现的类或抽象类。
工厂可以提供一个类型参数来向外界指定可以创建的产品种类。
* FACTORY METHOD通常应用于ABSTRACT FACTORY。在下面的PROTOTYPE中,PROTOTYPE因为无法区分子类,将要求INITIAL方法向对象创建提供支持,而FACTORY METHOD因为在实现的时候已经面向产品对象整理过了,因此不再需要额外的支持。
 
PROTOTYPE(原型)
PROTOTYPE应用于系统和产品相互独立时,而且PROPOTYPE常用于:产品类在运行时刻才能指定或者需要避免工厂类和产品类在层次上的相互平行趋势或者产品互相之间的区别仅在于一些共有的关键状态的不同时。
每注册一个PROTOTYPE就相当于向系统注册了一系列的产品。而且PROTOTYPE模式对RUNTIME时的增删提供支持。
由于对CLONE()方法的依赖,PROTOTYPE的实现可能需要DEEP COPY技术的支持,而CLONE()方法的实现也是一个需要注意的问题。
由于PRPTOTYPE的存在,类的动态定义和动态装载变得普遍起来。
* PROTOTYPE和ABSTRACT FACTORY可以一起使用,使系统的可定制化进一步提高。
 
SINGLETON(单件)
SINGLETON的应用使类在系统中仅仅存在一个实例。SINGLETON使得在整个系统中类只实例化一次。
SINGLETON在对象级别对全局变量的替代使得系统被全局变量危害的可能性降低。
* ABSTRACT FACTORY、BUILDER、PROTOTYPE都可以用SINGLETON模式实现。
 

2. 结构型模式
 
ADAPTER(适配器)
ADAPTER应用于在接口级别的接口方法转换,使得一个实际上提供某些接口的类体现出的是提供另外一些接口,ADAPTER使得原来不兼容的接口兼容化。
ADAPTER所作的是按照调用者的需求,提供和实体对象所不同的接口,并满足调用者的需要。
有两种方式来实现ADAPTER:一种是类适配器——定义一个新的类,它继承必需的接口和现有的实现,它使用多重继承;一种是对象适配器——将现有实现的实例包含到新的类的实例中,使用现有实例的接口实现必需的接口,它使用对象组合技术。
* BRIDGE模式和ADAPTER模式非常类似,但是BRIDGE分离了接口和实现,使这两部分可以比较独立地被加以改变,而ADAPTER则是通过从内部实现的改变提供对接口的支持。DECORATOR和ADAPTER的区别是,DECORATOR不对现有的接口做任何屏蔽和改变,而是原样将其暴露出来,因此DECORATOR可以递归而ADAPTOR则存在问题。PROXY所提供的接口则必定是实体对象提供出的接口集的子集,PROXY不修改接口。
 
BRIDGE(桥接)
BRIDGE分离了定义和实现,因此它至少有两部分,一部分为接口,负责抽象和定义,另一部分为实现类,负责定义的实现。这两部分应该在不同的层次结构中。
BEIDEG使抽象和实现之间没有固定的绑定关系,因此抽象和实现可以分别通过子类加乙扩充而对另一方没有影响,并且不同的抽象和实现可以进行组合并分别扩充(这保证了在编译时刻对实现部分的依赖性有所降低),同时,实现部分可以对用户透明。
* ABSTRACT FACTORY模式可以用来创建和配置一个特定的BRIDGE模式。
 
COMPOSITE(组合)
COMPOSITE的关键是一个抽象类,它既是组件也是容器。
COMPOSITE可以用递归的方式加以组合,在代码实现中,任何用到基本对象的地方都可以使用组合对象。
客户端代码可以不清楚实际使用的究竟是叶子节点还是组合节点。
新定义的字类也可以和原有的代码一起工作,而且不用改变任何原始代码。
如果你需要对某些时刻的使用类型加以约束,那么应该使用运行时类型检查。
* COMPOSITE与DECORATOR的不同在于COMPOSITE没有数量限制,而DECORATOR一次只能有两个对象参与;如果使用了FLYWEIGHT模式,则可以共享叶结点,但是因为无法确定对象标识,因此不能再引用它们的父节点;ITERATOR和VISITOR模式都可以使用COMPOSITE实现。
 
DECORATOR(装饰)
DECORATOR是将组件嵌入另一个对象中,这个对象被称作装饰(DECORATOR)。由这个对象来提供额外的隐藏接口,实现所需的功能,同时它也提供被嵌入的组件的所有接口。由于客户感觉不到装饰过与未装饰过的差别,因此装饰对客户将是透明的。
DECORATOR的透明性决定了可以递归嵌套多个装饰。
DECORATOR可以动态地给单个对象增加职责。
当可能出现大量的独立扩展使得子类的数目出现不可控增长或者类定义因被隐藏或其它原因而不能生成子类时可以考虑使用DECORATOR。
在实现上,DECORATOR和COMPONENT应该存在一个公共的COMPONENT父。
DECORATOR采用对象组合而非继承,因此比继承更加灵活。
DECORATOR允许在简单类的基础上用DECORATOR类组件逐渐添加功能,满足复杂的需要,同时也避免了在顶端出现不必要的特征。同时也避免了对基础类的依赖。
要注意的是,被装饰过的组件和未被装饰前是不一样的。
DECORATOR的缺点是会产生一些极为类似的小型对象,这些小型对象是为了提供极少量的特殊功能而定制的。
* DECORATOR和ADAPTOR的不同在于前者不改变接口而后者则提供新的接口。DECORATOR是一个退化的COMPOSITE,因为它一次只有2个对象参与。而且二者的目的也不同,DECORATOR不用与对象聚集。DECORATOR与STRATEGY的不同在于前者改变外观而后者改变内核。
 
FACADE(外观)
FACADE也可称为“集成接口”。它为系统中的一系列接口提供统一的对外界面。
FACADE可以为一个复杂子系统提供简单接口,并且因此对外接口的统一,使得客户程序或者其他子系统不可以深入到子系统内部,简化了子系统间的相互依赖,提高了子系统的独立性和可移植性。
FACADE并不强制性地限制子系统的入口。
FACADE对客户屏蔽了子系统组件,实现了客户和子系统间的松耦合。
将FACADE实现为抽象类,而使用它的具体子类应用于不同的子系统实现,这样可以进一步降低耦合。
可以考虑同时为子系统开发共有接口和私有接口,二者应用于不同的方面。
* ABSTACT FACTORY 可以和 FACADE一同使用以子系统独立的方式创建子系统对象。FACADE通常属于SINGETON模式。MEDIATOR在系统中的调用层次比FACADE低,参看MEDIATOR。
 
FLYWEIGHT(享元)
FLYWEIGHT应用于使用了大量对象的应用程序。若这些对象的大部分状态都可以转变为外部状态,且删除这些外部状态后,可以使用较少的共享对象取代大量对象,则使用FLYWEIGHT模式。
由于FLYWEIGHT模式下对象可以共享,因此应用程序不应使用对象标识来区分对象。
虽然使用FLYWEIGHT模式会产生外部状态传输/查找/计算的开销,但由于大量对象被取代从而节省了空间,因此这个开销是值得的。
* COMPOSITE和FLYWEIGHT可以结合使用,共享叶结点对象;FLYWEIGHT可以用来实现STATE和STRATEGY对象模式。
 
PROXY(代理)
PROXY用于为其它对象提供一个代理,用于控制对这个对象的访问。
使用PROXY的常见情况:
远程代理(REMOTE PROXY):为一个对象在不同的远程地址空间提供局部代表
虚代理(VIRTUAL PROXY):根据需要创建开销很大的对象
保护代理(PROTECTION PROXY):控制对原始对象的访问,保护代理用于对象应该有不同的访问权限的时候。
智能指引(SMART REFERENCE):以一个附加程序包的形式出现,作用类似于EJB结构中的。
* PROXY和ADAPTER的不同在于後者修改了原始对象的接口;PROXY与DECORATOR的不同在于DECORATOR增强了原始对象的功能(以增强/增加接口的方式),而PROXY则是控制对原始对象接口的访问(削弱对原始接口的无条件访问的可能性)。
 
 
3.行为型模式
 
CHAIN FO RESPONSIBILITY(职责链)
使多个对象都有机会处理请求,避免请求发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
职责链有三个组成部分:统一请求处理接口,处理者、发送者。
参考SWING中的组件消息传递模型
优缺点:降低耦合度;增强了给对象指派职责的灵活性;但不保证请求一定能被接受
* 职责链常和COMPOSITE一起使用,构件的父构件可作为它的後继。
 
COMMAND(命令)
COMMAND用于将一个操作请求对象化,以使得客户可以用参数化的方式发布命令。也即是说,命令的不同仅仅表现在参数的不同,而不是方法或接口的不同。
命令模式,要求所有该模式使用的所有参与对象实现命令接口。
以下情况可以考虑使用COMMAND:
1)需要将被执行的动作抽象以参数化某对象。考虑某些callback方法以及它们的使用。
2)对请求队列排序,在此情况下,与该请求相关的对象应该与可重用地址空间无关,防止对象被覆盖,或者至少能够保证对象的生存期。
3)支持取消操作,考虑在COMMAND对象中内嵌一个UNEXECUTE_METHOD()方法。注意的是取消操作的方法,其执行顺序和错误监测以及纠正,这些要点在本模式中不负责解释和解决。
4)支持修改日志。COMMAND对象中封装一个日志方法例如LOG方法,这样在崩溃后可以读入命令记录,并重执行之。
5)用构建在原语操作基础上的高级操作构造一个系统,这种结构通常可以支持事务,COMMAND模式提供了对事务进行建模的方法。
* COMPOSITE模式可以用来实现宏命令;MEMENTO模式可用来保持某个状态,COMMAND用这一状态取消它执行的效果。
 
INTERPRETER(解释器)
INTERPRETER主要用于语言及对其文法的某种表示的解释。
当定义了一个语言的文法的时候,提供一个解释器来解释该语言的文法。该解释器一般实现了一个抽象语法树,如果一个语言能够被实现为一个语法树的时候,可以使用解释器模式。
需要为一个语言中的每一个字元素定义一个解释类,当这些子元素的任意组合形式都能够被所对应的解释类集所解释的时候,可以认为已经创建了一个对于该语言的解释器。
优缺点:易于改变和扩展文法;易于实现文法;对复杂的文法就难以维护,不如语法分析器;但是可以增加新的解释方式。
* INTERPRETER和COMPOSITE有一些相同的地方,都需要多个类协同工作才能达到预定要求,而解释器的协同性和耦合性要求更高一些。如果需要频繁创建新的表达式解释方法,应该考虑使用VISITOR模式,避免基础文法解释类被频繁改动。
 
ITERATOR(迭代器)
迭代器模式用于顺序访问聚合中的元素。别名:CURSOR
迭代器模式的好处在于,该聚合中的元素的具体组合模式被屏蔽了,不需要暴露聚合本身,而以一个与该聚合相耦合并能够按某种固定顺序来读取聚合中元素的对象来负责聚合中元素的获取。
迭代模式简化了聚合的interface,并且允许一个聚合同时拥有多个ITERATOR,这些ITERATOR彼此可以是互相独立的,可以互不干扰地调整自身的迭代逻辑,最重要的是,不同的ITERATOR可以各自独立地同时对同一个聚合进行遍历而互不干扰。
对于不同的聚合,可以提供一个统一的遍历迭代接口。即支持多态迭代。
* 迭代器经常被用于COMPOSITE这样的复合结构上。用于遍历复合结构中的元素。多态迭代器使用FACTORY METHOD例化适当的迭代器子类。MEMENTO常与ITERATOR一起使用来捕获迭代状态,迭代器在内部保有一个MEMENTO。
 
MEDIATOR(中介者)
中介者用来封装一系列对象的交互。中介者使对象不需要显式地相互引用。从而降低了对象耦合度。并且,中介者可以相对独立地修改对象间的交互。
中介者适用于如下情况:
1)一组对象定义良好但是一复杂的方式通信,导致相互间的关系混乱,难以理解。
2)一个对象需要引用多个其他对象,并且直接与这些对象通信,导致该对象无法复用。
3)定义一个特定的需要多个类写作的行为,但是不想为该行为生成太多子类。
中介者的组成部分:中介者接口,中介者实现,协同类(协同类保有对中介者对象的引用,并且需要其他协同类写作的时候调用中介者对象)。
中介者模式的优缺点:减少子类生成;将各colleague解调;简化对象协议;对对象的协作进行抽象;集中控制。
* FACADE与中介者不同在于它是对一个对象子系统进行抽象,从而提供一个高层的对外接口。它的交互协议是单项的,即只允许FACADE向子系统类提出请求,FACADE的调用级别高于所有其他的子系统类。MEDIATOR提供了各colleague不支持或不能支持的协作行为,而且它的交互协议是双向的,FACADE与子系统中其他类可以互相提出请求。
 
MEMENTO(备忘录)
备忘录是在不破坏封装的情况下获得一个对象的内部状态,并独立于该对象保存该状态,便于以后将对象恢复到备忘录所保存的状态。
被备忘录所观察的对象被称为原发器(ORIGINATOR),只有原发器才保有对备忘录的访问入口,备忘录对其他对象不可见。
必须保有一个对象在某时刻的(至少部分)状态,这样才能在将来恢复到这些状态参数。如果备忘录被其他对象可见并有一个接口可以被访问,则可能破坏原发器的正常封装性。
原发器必须至少实现一个rollback接口。
备忘录保持原发器的封装别界,不至于暴露ORIGINATOR的内部信息。也可以简化原发器对自身对象的存储代价。但是备忘录本身代价可能很高。而且备忘录的管理器在管理过程中也会产生大量的存储开销。
在执行undo和redo操作时,考虑使用备忘录格式。
* COMMAND可以使用MEMENTO来为可撤销的操作维护状态。MEMENTO也可以ITERATOR一起使用(参看ITERATOR)。
 
OBSERVER(观察者)
观察者定义对象间的一对多的关系,当一个对象发生改变时,与其相关的所有对象都得到通知并自动更新。
又名依赖(DEPENDENTS)发布-订阅(PUBLISH-SUBSCRIBE)。
观察者适用于如下情况:
1)一个抽象模型有2方面,其中一个依赖于另一个,将二者独立封装使它们可以独立地改变和复用。
2)当一个对象需要改变并需要通知其他对象或需要其他对象一起改变,却不知道有多少对象要被通知或者不知道谁该被通知的时候。
OBSERVER允许目标和观察者之间的独立性,可以单独复用目标与观察者其中之一,也可以在不改动目标的情况下增加观察者。
观察者的优缺点:目标和观察者的抽象耦合;支持广播通信;但是某观察者对目标的改变可能会导致意外的更新情况出现。
* MEDIATOR,通过封装复杂的更新语义,changemanager充当target和observer的中介者;singleton,changemanager使用singleton保证自己是唯一的并且是可全局访问的。
 
STATE(状态)
允许一个对象在其状态改变时改变其行为,看似对象更改了他的类实现。
state将特定状态相关的行为局部化,并分割了不同状态的行为。也使状态的转换显式化(为不同状态引入独立对象 与 对对象中的变量赋值 相比,前者使转换显得更明确)。另外,state对象也可以被共享,使不同的context对象可以共享同一个轻量级的state对象。
* FLYWEIGHT模式解释了何时以及怎样共享状态对象。状态对象通常是一个singleton。
 
STRATEGY(策略)
定义一系列算法且封装起来,使它们可相互替换。使得算法可独立于使用客户而发生变化。
以下情况,使用STRATEGY:
1)许多相关的类仅仅是行为有异,STRATEGY使得可以用多个行为中的一个来配置一个类。
2)需要使用一个算法的不同变体,当这些变体实现为一个算法的类层次时(),可以使用STRATEGY。
3)算法使用用户不应该知道的数据,用STRATEGY避免暴露复杂的、算法相关的数据结构。
4)一个类定义了多种行为,这些行为在该类的操作中以多个条件语句的形式出现。可以将相关的条件分支移入STRATEGY中以代替条件语句。
STRATEGY的优缺点:相关算法系列(定义了可重用的算法,继承可析取算法中的公用功能);一个替代继承的方法(算法封装在STRATEGY中可以独立于context进行修改和切换);消除条件语句(行为封装在STRATEGY中,避免了不同的行为堆砌在一个应用类中,从而该应用类中不得不使用大量条件语句的情况)
* FLYWEIGHT,STRATEGY在其中可得到应用,STRATEGY是很好的轻量级对象,在享元模式中,轻量级对象是最好的享元组件。
 
TEMPLATE METHOD(模板方法)
TEMPLATE METHOD定义了算法的骨架,而将一些步骤延迟到子类中,使得子类不改变算法结构就可以重定义算法的某些特定部分。
应用于下列情况:
1)一次性实现一个算法中的不变部分,而可变部分由子类实现。
2)各子类的公共行为部分应被提取出来并集中到一个公共父类以避免代码重复。
3)控制子类扩展。使子类的扩展被限制在特定的范围内和特定的hook(钩子)点。
* FACTORY METHOD常被模板方法调用。模板方法使用继承来改变算法的一部分,STRATEGY使用委托改变整个算法。
 
VISITOR(访问者)
表示一个应用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的情况下定义作用于这些元素的新操作。
VISITOR模式的适用性:
1)一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于具体类的操作
2)需要对一个对象结构中的对象进行很多不同且不相关的操作,而又要避免这些操作污染相关的类。VISITOR使这些操作集中定义到一个类中。当该对象结构被共享时,VISITOR让每个应用只抱含需要的操作。
3)定义对象的结构很少被改变,但经常要定义新的操作,改变结构定义类需要改变所有使用该类的接口。
优缺点:易于增加新的操作;访问者集中相关的操作且分离无关操作;增加新的元素变得困难;但可以通过类层次进行访问;状态可能会被累积并无效地传递出去;很可能会破坏封装。
* COMPOSITE,访问者可以用于对一个由COMPOSITE模式定义的对象结构进行操作。INTERPRETER,访问者可以用于解释。
 
 
 
声明:本人保有对本文的一切版权。其它网站转载本文请保留原作者和本声明。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值