装饰模式(Decorator)
装饰模式(Decorator或 Wrapper)(Java IO过滤流用到的正是这个模式):
之前总是先罗列基本概念再介绍代码,这次先把代码罗列出来再写基本的概念
以上是UML类图,先把基本的代码罗列出来:
package com.designpatten.decorator; interface Component { public void doSomething(); } package com.designpatten.decorator; public class concreteComponent implements Component{ public void doSomething() { System.out.println("功能A"); } } package com.designpatten.decorator; abstract class Decorator implements Component { private Component component; public Decorator (Component component){ this.component=component; } public void doSomething() { //调用的是传进来的component component.doSomething(); } } package com.designpatten.decorator; public class concreteDecoratorA extends Decorator{ public concreteDecoratorA(Component component) { super(component); } public void doSomething(){ super.doSomething(); this.doAnotherthing(); } public void doAnotherthing(){ System.out.println("新添加的功能C"); } } package com.designpatten.decorator; public class concreteDecoratorB extends Decorator { public concreteDecoratorB(Component component) { super(component); } public void doSomething(){ super.doSomething(); this.doAnotherthing(); } public void doAnotherthing(){ System.out.println("新添加的功能B"); } } //最终的测试类 package com.designpatten.decorator; public class decoratorTest { public static void main(String[] args) { //类似IO流的方式来定义 这里与IO过滤流的使用方式是一致的 Component component1=new concreteDecoratorA(new concreteDecoratorB(new concreteComponent())); component1.doSomething(); Component component2=new concreteDecoratorA(new concreteComponent()); component2.doSomething(); Component component3=new concreteDecoratorB(new concreteComponent()); component3.doSomething(); } } //输出结果 /* 功能A 新添加的功能B 新添加的功能C 功能A 新添加的功能C 功能A 新添加的功能B */
定义:
所谓装饰类就是把客户端的调用委派到被装饰类中,装饰模式的关键是在于这种扩展是一种完全透明的方式。比如某种装饰的方式:
Component component2=new concreteDecoratorA(new concreteComponent());
component2.doSomething();
调用component2的doSomthing方法,首先是调用其父类(concreteComponent)的doSomething方法,这个是最初版本的doSomething方法,之后再调用扩展的方法(这里有个递归的含义在里面 多层乞嵌套的时候 super.dosomthing()会一直向上递归 直到最初定义的dosomthing()方法),这样就实现了功能的扩展,由于各个concreteComponnet类都是继承component接口,这种扩展可以以嵌套的方式多层地进行。装饰模式可以在不必改变原来类文件和使用继承的情况下,动态地扩展一个对象的功能,他是通过创建一个包装对象用于包裹真实的对象。
特点:
1、 装饰模式以对客户端透明的方式来扩展对象的功能,是继承方式的一种替代方案。
2、 装饰模式以对客户透明的方式动态地给对象附加更多的责任,换言之,客户端并不会觉得对象在装饰前与装饰之后有什么不同。
3、 可以在不创建更多类的前提下,将对象的功能进行扩展。
就像在IO中 BufferInputstream DataInputstream FileInputstream三个类可以进行组合,但是并没有增加类的数目。比如上面的例子,通过基本的三个类,可以组合出实现功能A 功能B 功能C 以及分别实现功能A 功能C 和功能A和功能B 等等,不同的功能,但是最后并没有增加新的类,仅仅是通过对原有的几个类进行组合而完成的。
可以看出来几个基本的角色(对应IO来说):
1、 抽象的构建角色(Component)给出了一个抽象的接口,用来规范准备接收的附加责任对象。
2、 具体构建角色(concreteComponent)
3、 装饰角色(Decorator)持有一个构建对象的引用作为属性,并定义一个与抽象构建接口一致的接口,注意:装饰角色会实现抽象构建角色的接口,通过构造函数传递一个具体的构建角色进来。
4、 具体装饰角色(concreteDecorator)负责给构建角色贴上附加功能。
装饰模式与代理模式的区别:
其实,它们的着重点一个在于“增加”职责(装饰者模式),另一个在于“控制”访问(代理模式)。这是它们最本质的区别。使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造,可以灵活地以不同的方式进行组合,具体的区别可以参考:
http://hi.baidu.com/springlie/item/834cb0e3fa778db52e140b48
http://www.cnblogs.com/jaredlam/archive/2011/11/08/2241089.html
代理模式无法嵌套调用
代理模式主要体现在对代理的对象施加控制,并不提供对象本身的增强功能,也就是说在代理模式下,那个先前的预处理的部分,可以修改成为权限控制的模块,如果当前传入进来的类的实例权限不够,就无法往下走,去访问被代理的对象的核心的方法。
在网上找了一些相关的信息 貌似是这个样子:
貌似是实现的机制很类似,特别是静态代理与装饰模式,但是它们最终的功能还是相反的。一个是增加功能,一个是权限限制。一说权限判断,就指的是代理模式,一说添加功能,就指得是装饰模式,虽然实现上两者确实很类似,差别主要是意图上的。
装饰模式与继承的区别:
1、继承是用来扩展一类对象的功能,需要子类,是静态的,在编译的时候才分配具体的职责,这样会导致很多的子类产生,比较缺乏灵活性。
2、装饰模式是用来扩展特定对象的功能,并不需要生成新的子类,并且是动态进行的,只需要对已有的对象进行不同的组合,在运行的时候才分配职责,这样可以防止子类过多导致的混乱,并且更加灵活,对与一个给定的对象,可以同时被不同的包装类进行包装。
3、装饰者模式可以动态地给一个对象增加其他职责。就扩展对象功能来说,装饰者模式比通过继承来生成子类更为灵活。所谓动态是说可以在系统运行时(RunTime)动态给对象增加其它职责而不需要修改代码或重新编译;所谓静态是说必须通过调整代码(DesignTime)才能给对象增加职责,而且系统还需要重新编译。