最近由于忙着准备实习单位的面试,加上导师的任务,所以更新的有点慢,希望大家能谅解。
下面继续。
Decorator
描述:
动态、透明的为对象添加职责。
适用性/作用:
该模式有两个主要参与者,Decoratee和Decorator。前者为原有的对象,而后者则是在前者的基础上添加了新的功能。在GOF的描述中,Decorator和Decoratee使用了相同的接口。同时大部分的相关材料都侧重于这一模式“添加职责”的功能。但是有一点个人认为,在该模式的使用中还有两点值得考虑。
首先,Decorator和Decoratee不仅在继承体系中属于同一层,在整个系统的功能体系中也应当是平级的。Decoratee自身也需要有相当的可能性被独立的使用到,否则在两个对象之间建立Decorator-Decoratee的关系就不那么必要,也许将Decoratee在功能体系中下移是个更好的选择,因为它会避开“相同接口”这样一个限制;
其次,Decorator之间的功能划分最好是正交的。一旦Decorator之间出现了不一致性,那么Decorator的装饰次序将会影响到实际的结果,或者对某个Decorator而言Decoratee存在着限制。而这些运行时才有的特性很难在静态设计中体现出来,会造成对系统功能的理解造成障碍。
Facade
描述:
为子系统中的一组接口提供一个统一的界面
适用性/作用:
由于子系统间的类联系比较紧密,他们通常会一一种固定的协作方式完成某项任务。当客户代码多以这种粗粒度的方式与子系统打交道时,Facade模式便有必要起来。
Facade模式可以用来解决以下两个问题。
第一,如果某种粗粒度任务都是由一系列的细粒度组件以一定的语义关系耦合起来。而客户代码只关心这种粗粒度的任务,但不关心这个任务究竟怎样由子系统的组件合作完成的。那么这是,可以使用Facade模式将细粒度之间的语义耦合封装起来,并且这种封装可以防止子系统组件间合作的改变对客户代码造成影响。
第二,也就是GOF所描述的,简化客户使用子系统的复杂度。
Facade本身的设计在实践过程中会遇到以下几种情况。
第一种情况下,Facade本身具有很高的内聚,同时它完全封装了子系统(说明子系统内聚度高),客户代码不需要知道子系统的细节便可以用Facade完成全部的工作。这一点是最理想的情况。
更多的可能是,Facade不能包办一切,程序既要与子系统打交道,也要与Facade打交道。这种情况下,如果Facade使用不当,便会破坏系统的层次结构。
个人的经验是,
如果一些子任务可以由Facade封装而完全不需要与子系统打交道,便对子系统的部分粗粒度任务使用Facade模式,保持局部的内聚性和抽象能力;
如果一个功能,客户通常都直接调用Facade,但是在少数情况下不可避免的要与细粒度组件打交道,那么通常我会将Facade旁置为一些Help Function,让它们与子系统组件处于差不多同样的地位,并以文档显示地注明其实现原理。
当然,能通过修改子系统的设计避免这种情况的出现是最完美的结局了。
Flyweight
适用性/作用:
呃,关于这个我想GOF已经描述的非常好了,我也就不说废话了。注意Flyweight在其它模式中的应用就行了。我经常就会在该用它的时候忘了用了。Flyweights通常由pool手法实现。
Proxy
适用性/作用:
Proxy的目的很明确,在维持原有接口和功能设计情况下,解除原始对象的限制。这最后的一句话是我的理解。通常一个对象实现一个功能直接实现就可以了;但是在一些应用中,会有一些与功能无关的限制和要求,例如对象可能是远程的,或者有内存方面的限制等等。为了解除这些限制,需要一些额外的手法来达到这样的目的。但是它们所附加的内容在功能设计时并没有描述。也就是说,这些不是客户需要关心的,它们应该被抽象掉。Proxy就是为了隐藏这些与代码的核心功能无关的实现,让客户端认为它是个没有限制的对象。
对象型模式讲完了,下面的行为型模式我大概分两次讲,欢迎大家的板砖。