设计模式-装饰模式(Decorator)在jDK中IO系统的应用该模式在java中比较典型的应用也就是jdk的io系统了?? ?
设计模式-装饰模式(Decorator)在jDK中IO系统的应用
该模式在java中比较典型的应用也就是jdk的io系统了
?? ?装饰模式类图
?? ?
好吧,其实这类图只对UML熟悉的人才有用,装饰模式有啥用?说白了就是在原来类的功能上,对这些功能做一些增强处理,当然为了增强功能而通过继承也是一种有效的方式,当然对于各种组合比较多的情况下,使用继承可能会有太多的类出现,所以就需要使用装饰模式,当然装饰模式的缺点也是显而易见的,使用上会比较麻烦。
举个例子:
?? FileReader
?? StringReader
?? 我要为这两个类的read功能增加缓存功能,如果使用继承方式,我需要两个子类来完成,也许这两个子类得叫BufferedFileReader和BufferedFileStringReader,如果要增加缓存功能的类有十个,那么子类也就需要十个,但是如果用装饰模式,我只要增加一个装饰类既可满足,BufferedReader类,这个就是jdk1.1的io系统设计。
普通的装饰模式简单示例
view plaincopy to clipboardprint?
- //总接口??public?interface?Compoent?{??
- ????public?Object?needGirl();??}??
- ??//执行类??
- public?class?GirlGet?implements?Compoent?{??????public?Object?needGirl()?{??
- ????????//?TODO?Auto-generated?method?stub??????????System.out.println("给你个素颜的女优美眉");??
- ????????return?null;??????}??
- }??//装饰类父类,可有可无??
- public?abstract?class??Decorator?implements?Compoent?{??????public?abstract?Object?needGirl();??
- }??//装饰类??
- public?class?MakeUpDecorator?{??????private?Compoent?c?=?null;??
- ????public?MakeUpDecorator(Compoent?_c)?{??????????this.c?=?_c;??
- ????}??????public?Object?needGirl()?{??
- ????????//?女孩化妆??????????girlMarkUp();??
- ????????return?c.needGirl();??????}??
- ????public?void?girlMarkUp()?{??????????//?化妆??
- ????????System.out.println("素颜的女优不好,化妆下!");??????}??
- }??//客户端??
- public?class?Client?{??????public?static?void?main(String[]?ben){??
- ????????MakeUpDecorator?mud?=?new?MakeUpDecorator(new?GirlGet());??????????mud.needGirl();??
- ????}??}??
?
套用io模式的BufferedReader,StringReader,Reader的read功能来做说明:
首先来说明这三个类在上述类图的位置:
Reader:Compoent也是Decorator的基础类
StringReader:ConcreateComponent
BufferedReader:ConcreateDecoratorA
写出简略代码,从jdk1.1中的源码抠出来,去除了很多与该模式无关的代码:
+ expand sourceview plaincopy to clipboardprint?·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150?view plaincopy to clipboardprint?
- //BufferedReader??public?class?BufferedReader?extends?Reader{??
- ???private?Reader?in?=?null;?????cb?=?new?char[sz];??
- ???public?BufferedReader(Reader?reader)[????????in?=?reader;??
- ???}?????public?int?read(char?cbuf[],?int?off,?int?len)?throws?IOException??
- ???????int?n?=?read1(cbuf,?off,?len);?????????if?(n?<=?0)return?n;??
- ???????while?((n?<?len)?&&?in.ready())?{?????????????int?n1?=?read1(cbuf,?off?+?n,?len?-?n);??
- ???????????if?(n1?<=?0)break;?????????????n?+=?n1;??
- ???????}?????????return?n;??
- ???}?????private?int?read1(char[]?cbuf,?int?off,?int?len)?throws?IOException?{??
- ???????if?(nextChar?>=?nChars)?{?????????????//当读取的长度超过缓存长度的时候,直接从in里面读取,也就失去了这个装饰类的作用了。??
- ???????????if?(len?>=?cb.length?&&?markedChar?<=?UNMARKED?&&?!skipLF)?{?????????????????return?in.read(cbuf,?off,?len);??
- ???????????}?????????????//如果读取的下个字符索引超过了当前的缓存长度,也就是说不在缓存中,那么重新加载下一组缓存.??
- ???????????fill();?????????}??
- ????//当加载缓存后发现,读取的下个字符索引仍旧超过缓存长度,其实就是加载下一组失败,也就是说已经读取完毕了。??????if?(nextChar?>=?nChars)return?-1;??
- ????int?n?=?Math.min(len,?nChars?-?nextChar);??????//从缓存中读取字符??
- ????System.arraycopy(cb,?nextChar,?cbuf,?off,?n);??????nextChar?+=?n;??
- ????return?n;??}??
- ????private?void?fill()?throws?IOException?{?????????//创建一个缓存,缓存的长度可设置,为设置是默认的??
- ???????//首先从in中获取指定长度的流到缓存中去。加速访问.?????????//核心语句就下面一句??
- ???????n?=?in.read(cb,?dst,?cb.length?-?dst);??????}??
- }??
?
从上面可以看出,BufferedReader类其实就是将Reader的子类(ConcreateComponent)也就是这里的StingReader的数据放入缓存,然后操作read方法的时候,从缓存中读取,但是实际上的流还是通过StringReader来获取的。也就是说BufferedReader对StringReader类的read功能增加了缓存功能,在事实上,你不使用BufferedReader也可以直接操作StringReader的read功能,只是没有了缓存效果而已。
客户端使用的代码:
String s = "This is the\n\ninternal StringReader buffer.\ndderwe";?
StringReader stringReader = new StringReader(s);?
BufferedReader bufReader = new BufferedReader(stringReader);?
可以看到,客户端使用是比较麻烦的,这就是装饰模式的缺点。