参考链接1:http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html
参考链接2:http://www.cnblogs.com/ASPNET2008/archive/2008/06/15/1222724.html
定义
装饰器模式:在不改变原类和不生成子类的情况下,动态为对象添加额外的职责。其比继承更灵活、更具弹性。
设计原理
不改变原类扩展功能,符合开闭原则(对修改关闭,对新增开放);
不通过子类扩展功能,可以让类设计更灵活。因为继承实现子类行为,编译是静态的;而用组合扩展功能,则可以在程序运行时动态扩展。
类图
在客户端中对ConcreteComponent进行装饰的语句就为:
AbstractDecorator decorator = newConcreteDecorator2(new ConcreteComponent());
decorator实例接口与被装饰者接口(operator())保持一致,但客户端通过装饰器示例调用operator()方法时,功能已可以被动态增加。组成要素
1) 抽象角色(IComponent):给出一个抽象接口,以规范准备接受附加职能的对象。
2) 具体角色(ConcreteComponent):被装饰者,其实现接口与抽象角色保持一致。
3) 抽象装饰角色(AbstractDecorator):装饰器,实现并聚合了抽象角色。实现抽象角色是为了装饰者与被装饰者保持相同的对外接口;聚合了一个抽象角色,是为了通过此角色,在运行时动态调用某一具体角色。
4) 具体装饰角色(ConcreteDecorator):需要扩展功能的动态实现,具体的装饰器。
常见例子
1) servlet中的装饰器HttpServletRequestWrapper。HttpServletRequest类的getParameter()方法:装饰前调用此方法,只是简单返回参数值,而不会对此参数做任何处理;用HttpServlertRequestWrapper装饰后,重写getParameter()方法,可以对参数值进行trim()操作。
2) IO操作之一:BufferedInputStream对FileInputStream装饰:
BufferedInputStream buf = new BufferedInputStream(newFileInputStream(“filePath”));
类图如下:FilterInputStream相当于抽象装饰器角色,FileInputStream是被装饰的角色,InputStream抽象类是装饰器与被装饰器共同的规范,BufferedInputStream则是具体的装饰实现。换句话说,这里的BufferedInputStream是对FileInputStream装饰了缓冲区功能,若实际需求中你对FileInputStream现有功能不满,你可以自定FilterInputStream的子类,实现自己的装饰器。
代码示例
举例实现三个装饰器,每个扩展一个功能,在客户端调用装饰器时,对其进行了三次装饰,那么装饰器示例三个功能都具备。
1) 抽象角色:
public interface ISource {
public void operatrion();
}
2) 具体角色:
public class SourceImpl implements ISource {
public void operatrion() {
System.out.println("*****装饰器原始类,原始功能调用*****");
}
}
3) 抽象装饰角色:
public abstract class AbstractDecoratorSource implements ISource {
private ISource source;
public AbstractDecoratorSource(ISource source){
this.source =source;
}
public void operatrion(){
source.operatrion();
}
}
4) 具体装饰角色,A、B、C:
public class DecoratorSourceA extends AbstractDecoratorSource {<span style="white-space:pre"> </span>//装饰A
public DecoratorSourceA(ISource source){
super(source);
}
@Override
public void operatrion() {
System.out.println("装饰器A前");
super.operatrion();
System.out.println("装饰器A后");
}
}
public class DecoratorSourceB extends AbstractDecoratorSource {<span style="white-space:pre"> </span>//装饰B
public DecoratorSourceB(ISource source){
super(source);
}
@Override
public void operatrion() {
System.out.println("装饰器B前");
super.operatrion();
System.out.println("装饰器B后");
}
}
public class DecoratorSourceC extends AbstractDecoratorSource {<span style="white-space:pre"> </span>//装饰C
public DecoratorSourceC(ISource source){
super(source);
}
@Override
public void operatrion() {
System.out.println("装饰器C前");
super.operatrion();
System.out.println("装饰器C后");
}
}
5) 客户端调用测试
public class Test {
public static void main(String[] args){
ISource source = new SourceImpl();
//可以多次装饰,每次装饰都可以为前一个基础类添加新的功能
source = new DecoratorSourceC( //一次装饰
new DecoratorSourceB( //二次装饰
new DecoratorSourceA(source)));//三次装饰
source.operatrion();
}
}
6) 输出结果: