装饰器模式与适配器模式区别
适配器模式
对适配器模式的功能很好理解,就是把一个类的接口变换成客户端所能接受的另一种接口,从而使两个接口不匹配而无法在一起工作的两个类能够在一起工作。
适配器模式的结构:
- target(目标接口):所要转换的所期待的接口
- Adaptee(源角色):需要适配的类
- Adapter(适配器):将源角色适配成目标接口,一般持有源接口的引用(或者继承源接口),且实现目标接口。
Java I/O中的适配模式
适配器的作用就是将一个接口适配到另一个接口。在 JAVA的IO类库中有很多这样的需求,如将字符串数据转变成字节数据保存到文件中,将字节数据转变成流数据等。下面以InputStreamReader和OutputStreamWriter 类为例介绍适配器模式。
InputStreamReader继承Reader,但是要创建它们的对象必须在构造函数中传入一个 InputStream的实例,InputStreamReader也就是将 InputStream适配到Reader。
InputStreamReader继承了Reader抽象类并实现,且持有了InputStream的引用,这里是通过StreamDecoder类间接持有的,因为从byte到char要经过编码。
很显然,适配器就是InputStreamReader,源角色就是InputStream代表的实例对象,目标接口就是Reader类。OutputStreamWriter 也类似。
- StringReader将一个string类适配到Reader接口
- ByteArrayInputStream适配器将byte数组适配到InputStream流接口处理
装饰者模式
装饰着模式,顾名思义,就是将某个类重新装扮一下,使得它比原来更“漂亮”,或者在功能上更强大,这就是装饰器模式所要达到的目的。但是作为原来的这个类的使用者还不应该感受到装饰前与装饰后有什么不同,即用法不变,否则就破坏了原有类的结构了,所以装饰器模式要做到对被装饰类的使用者透明,这是对装饰器模式的一个基本要求。
- component : 抽象组件角色,定义一组抽象的接口,规定这个被装饰组件都有哪些功能
- concreteComponent:实现这个抽象组件的所有功能。
- Decorator:装饰器角色,它持有一个component对象实例的引用,定义一个与抽象组件一致的接口
- ConcreteDecorator:具体的装饰器实现者,负责实现装饰器角色定义的功能
JAVA IO中的装饰器模式
前面介绍了装饰器模式的作用就是赋予被装饰的类更多功能,在java I/O 类库中有很多不同的功能组合情况,这些不同的功能组合都是使用了装饰器模式事项大的,下面以FilterInputStream为例介绍装饰器模式的使用。
下图是FilterInputStream的类结构图:
InputeStream 类就是以抽象组件存在的:而FileInputStream就是具体组件,它实现了抽象组件的所有接口;FilterInputStream类无疑就是装饰角色,它实现了InputStream类的所有接口,并且持有InputStream的对象实例的引用;
BufferedInputStream是具体的装饰器实现者,它给InputStream类附加了功能,这个装饰器类的作用就是使得InputStream读取的数据保存在内存中,而提高读取的性能。
与这个装饰器类有类似功能的还有LineNumberInputStream(java 1.8 已经过期)类,它的作用就是提高行按行读取数据的功能,它们都是InputStream类增强了功能,或者提升了性能。
适配器模式与装饰器模式的区别
- 装饰器与适配器都有一个别名叫做 包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的很不一一样。适配器模式的意义是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的
- 而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的。