java装饰者模式,通常用于一个需求方法需要有多种扩展功能组合的场景。
优点是对于需要额外功能时,客户端可以动态组合。当需要对原有被装饰类方法增加多个增强功能时,也不会造成大量的增强类。
java Io就是这么一个场景。
如读取字节流,而来源可以是文件或者java主存中的byte Array数组中。
而为了性能问题,我们通常会在java主存中生成一个缓存数组用于批量从底层文件或byte Array数组获取数据。这样就不需要每读取底层存储时调用系统io中断获取数组(对于FileInputStream来讲),以此达到性能。
而为了达到缓冲读取数据的目的,一种是我们分别对文件来源或byte Array数组来源,分别定义两个类,BufferedInputStreamForFile,BufferedInputStreamForByteArray。但这样也就导致多了很多类似BufferedInputStreamForFile这样的类。如果系统中数据获取来源有n个,那也就意味着要定义n个BufferedInputStreamForX的类。
BufferedInputStream最终要调用FileInputStream的read多个字节的api:
public int read(byte b[], int off, int len) //将对应文件内容读取到b数组,读取len个字节,存储从b数组的off开始。
装饰者模式可以有效改善这种情况。
装饰者模式中,有以下几个角色:
1.抽象构件类(被装饰的类的接口或抽象类)
2.具体构件类(被装饰者)
3.抽象装饰者
4.具体装饰者(具体实现增强功能的装饰类)
在java Io中,InputStream对应于所有被装饰者的接口类(抽象构件类)。具体构件类是FileInputStream。而抽象装饰者则是FilterInputStream。每一个具体装饰者实际上对应一个增强功能,如BufferedInputStream就是具体装饰者,用于改善读取底层数据的性能。
事实上整个装饰者模式实现的核心原理还是基于类似代理的原理。客户端调用一个被装饰过的类时,最终会先执行具体装饰者实现的方法,具体装饰者会在方法前执行一些动作(如有),然后调用实际被装饰的类去执行核心功能,最后做完后再执行一些其它逻辑(可选)。
java io 源代码:
BufferedInputStream bin=new BufferedInputStream(new FileInputStream("/Usersa/Documents/temp/a.txt"));
int res=bin.read();
这段代码中BufferedInputStream是具体装饰者,实现了对于底层读取缓冲读取的增加功能。BuffredInputStream继承了抽象装饰者类FilterInputStream。
而FileInputStream则是具体被装饰者,是真正从底层来源获取数据的类。