装饰的含义就是在原有的物件上增加饰品,使得物件能呈现出不同的特征。当然在类设计中,采用装饰模式,是用来为类增加新的特征和行为。结构如下:
*
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | Component |<-------------------------------------------------------------------|
* |----------------------- -----| |
* | Operation() | |
* |________________| |
* △ |
* | |
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| |
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|◇-Component------|
* | ConcreateComponent | | Decorator |
* |--------------------------------------| |---------------------------------------| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | Operation() | | Operation() ○---------------|--→| Component-> Operation() |
* |_________________ ___| |______________________| |_____________________|
* △
* |
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | ConcreateDecoratorA | | ConcreateDecoratorB |
* |--------------------------------------| |---------------------------------------| | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
* | Operation() | | Operation() ○-------------|-→| Decorator:: Operation() |
* | addedState | | AddedBehavior() | | AddedBehavior() |
* |_____________________| |______________________| |_________________ ___|
*
角色:
抽象构件(Component):给出一个抽象接口,以规范准备接收附加责任的对象。
具体构件(Concrete Component):定义一个将要接收附加责任的类。
装饰(Decorator):持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Concrete Decorator):负责给构件对象“贴上”附加的责任。
装饰模式有两种实现模式,一是如上图所示采用委托的方式进行,二是采用子类化的方式进行,但从装饰的本意来讲还是采用委托的方式比较好。采用委托的方式可以动态,灵活的为对象增加新的责任和功能。
总结:
A)装饰模式并不改变构件原有的行为和特征,只是增加新的行为和特征,与适配器模式不同,装饰者只改变对象的责任,而非接口。而适配器模式让对象有一个全新的接口。
B) 虽然装饰模式可以视为组合模式只有一个组件的特例,但装饰者主要是为了附加责任而非对象聚合(aggregation)。
C)装饰模式和策略模式都可以让你改变对象,但装饰者模式只改变对象的外表,而策略模式是改变对象的内部。
D)采用子类化本身就可以增加新的特征和行为,但采用这种方式在需增加的特征和行为比较多样化的情况下,会使得类体系过于庞大,而装饰模式因为装饰和构件是组合方式进行,因此不仅灵活,而且也可以减少类的数量。而且不是所有情况下都可以采用子类化的方式进行(比如具体构件是密封类)
E)装饰模式比静态继承更灵活;而且可以避免在层次结构较高的类具有太多的特征;但缺点是会产生很多小对象(饰件);虽然Decorator从Component继承,但其本身与Component不是同一种对象,因此在命名上应特别注意,不要让用户产生误会。
F)装饰模式和桥模式都可以用来减少类(如果构件本身没有演化,或者演化很简单,则装饰模式并不能家少类,反而会增加类)的数量,都可以避免复杂的继承结构,。但也有如下区别:
1)在结构上两者有区别(比较图就知道)
2)实现方式上不同:装饰模式是通过将构件的核心功能和附加功能分离,类本身体系独自变化,而将附加性功能交给装饰子类,这样核心功能和附加功能各自独立变化,通过装饰子类对构件的封装来实现动态的为组建提供附加的功能。而桥模式则是将抽象行为的实现细节独立出来,构造一个实现化结构,通过抽象体系结结构和实现结构体系的组合达到适应变化的目的。
3)而且应用中,不同的装饰模式可以同时使用(比如对于对于图片,可以加边框,加滤境。而桥模式中的不同具体实现则不能同时应用。
4)装饰件是独立的,构件部分可以不使用饰件,而桥模式中实现部分只是相对独立,抽象部分必须依赖实现部分进行工作。
装饰模式也是包装模式的一种。
后记:虽然在装饰模式中我们不建议使用子类化方式来实现,但在实际应用中,有的时候我们还是需要用这种方式来实现,因为利用委托的方式来实现,装饰只能特定于某类构件,在我们需要装饰一些列类型的构件时,就无法实现。虽然采用子类化来实现大量增加装饰类,而且如果要重复装饰类的增加量就更大,但由于动态编译和动态中间语言指令注入的使用,这些子类可以动态生成,这就为所谓的AOP(面向方面编程)提供了一种可能。实际上Spring.Net 的AOP编程就是利用了装饰模式,而且是子类化。原因非常简单这种场景需要增加附加责任,但同时要求装饰必须与构件保持一致接口。Spring里面的AOP就是装饰模式+动态代码注入(动态编译或者利用EMIT)的利用,当然这种利用也进行了改良,通过结合观察者模式,将要附加的责任类作为观察者注入,这样,装饰类仅仅是按照一定的规则调用需要增加的责任类,大大减少了装饰类本身的数量,同时也增加了灵活性,不过这种情况下,装饰类本身的执行逻辑就变得复杂起来,特别是对于前置通知的处理,如果前置通知会影响是否真正执行具体任务类责任方法,在多个这样的前置通知下是一票否决制度,还是选票制度,就很难选择,而且如果具体责任类与通知类耦合很紧密的话,也不适合这种模式。Spring.net里的AOP注入虽然已经考虑得比较全面,但从可控性来讲,要完成这种横切目标最好的办法是在设计的时候就考虑到,而采用虚模式或其它方式来实现,不一定非得去使用AOP模式。一句话就是不要为了应用一种技术而应用一种技术。
分享到:
相关推荐
设计模式--装饰者模式java例子
设计模式--装饰模式 设计模式--装饰模式 设计模式--装饰模式 设计模式--装饰模式
23种设计模式--装饰模式
设计模式专题之(七)装饰模式---设计模式装饰模式示例代码(python--c++)
JAVA设计模式例程-装饰模式-的例程,看完以后基本上能对JAVA上实现装饰模式能有所了解,个人认为常各种模式并不是为了死套各种模式,而应该是灵活的在项目中结合实际情况而用各种模式的组合应用,呵呵!但前提是得对...
设计模式 - 装饰模式(C++实例) 若有问题,请指出。
设计模式-装饰模式(讲解及其实现代码)
c++设计模式-结构型模式-装饰器模式;QT工程;c++简单源码; 装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
JAVA-设计模式-结构型模式-装饰模式
装饰工程-装饰工程系统-装饰工程系统源码-装饰工程管理系统-装饰工程管理系统java代码-装饰工程系统设计与实现-基于springboot的装饰工程系统-基于Web的装饰工程系统设计与实现-装饰工程网站-装饰工程网站代码-装饰...
设计模式 - 装饰者模式
设计模式07-组合模式、装饰模式 设计模式09-外观模式、享元模式 设计模式10-代理模式、结构型模式大复习 设计模式11-行为模式-责任链、命令模式 设计模式12-解释器模式 设计模式13-迭代器模式 设计模式14-中介者模式...
装饰者模式:动态地将责任附加到对象上,若要扩展对象,装饰者模式提供了比继承更弹性的替代方案
java常用设计模式-装饰器模式
HeadFirst 设计模式学习笔记3--装饰模式 Demo http://blog.csdn.net/laszloyu/archive/2010/05/12/5582561.aspx
设计模式—装饰者模式,介绍的非常详细,讲解透彻
54-Spring设计模式之装饰器模式1