Java IO设计模式(装饰模式与适配器模式)
01. 装饰模式
1. 定义
Decorator装饰器,就是动态地给一个对象添加一些额外的职责,动态扩展,和下面继承(静态扩展)的比较。因此,装饰器模式具有如下的特征:
- 它必须持有一个被装饰的对象(作为成员变量)。
- 它必须拥有与被装饰对象相同的接口(多态调用、扩展需要)。
- 它可以给被装饰对象添加额外的功能。
总结:保持接口,动态增强性能。
装饰器通过包装一个装饰对象来扩展其功能,而又不改变其接口,这实际上是基于对象的适配器模式的一种变种。与对象的适配器模式异同:
- 相同点:都拥有一个目标对象。
- 不同点:适配器模式需要实现旧接口,而装饰器模式必须实现相同接口。
适配器模式是在适配器中,重写旧接口的方法来调用新接口方法,来实现旧接口不改变,同时使用新接口的目的。新接口适配旧接口。
而装饰模式,是装饰器和旧接口实现相同的接口,在调用新接口的方法中,会调用旧接口的方法,并对其进行扩展。
2. 由来(为什么不是继承)
功能的拓展,通常可以使用继承的方式解决。但这样实现的话,每一种组合都需要一个类,大量重复性内容,类数目“爆炸”;另外,这些拓展的功能必须要是可以预见,编译时就确定了,静态的扩展。
一个例子大概说:Beverage是一个抽象类,它被所有在一个咖啡店里卖的饮料继承。Beverage有个抽象方法cost,所有的子类都要实现这个抽象方法,计算它们的价格。现在有四个最基本的咖啡:HouseBlend,DarkRoast,Decaf,Espresso他们都继承自Beverage,现在的需求是说在四个最基本的咖啡里,每个都可以随便地添加调味品,像steamed milk,soy,还有mocha最后是加上whipped milk。如果是说按继承来实现这种几个调味品跟原来咖啡的组合的话,我们会很自然地设计来下面的类图来:

如果是按装饰模式的设计思路我们可以得出下面的设计类图:

装饰模式是怎么达到不仅类的数目大减少了,性能的重复也可以减至到最少。
3. 典型结构图

一句话解释:装饰者和被装饰者需要继承同一个接口或者是抽象类,被装饰者作为装饰者的一个变量。程序中原来调用被装饰者某方法func1的地方改成调用装饰者相同的那个方法func1,并且装饰者的该方法func1上添加了一些额外的功能,在方法func1中再调用被装饰着的方法func1。
这就是动态的扩展。
02. 适配器模式
目的:将一个类的接口转换成客户期望的另一个接口,让原本不兼容的接口可以合作无间。
1. 特点
- 适配器对象实现原有接口
- 适配器对象组合一个实现新接口的对象(这个对象也可以不实现一个接口,只是一个单纯的对象)
- 对适配器原有接口方法的调用被委托给新接口的实例的特定方法(重写旧接口方法来调用新接口功能。)
2.例子
我国国标充电器三孔,德国得标充电器两孔。现去德国旅行。如何将我们的三孔充电器插入两孔。这就需要适配器。
类图:

DBSocketInterface:德标接口
DBSocket:德国插座(实现DBSocketInterface,提供两孔充电方法)
Hotel : 拥有得标接口。
GBSocketInterface :国标接口
GBSocket : 中国插座(实现GBSocketInterface,提供三孔充电方法)
适配器实现:
public class SocketAdapter
implements DBSocketInterface{ //实现旧接口
//组合新接口
private GBSocketInterface gbSocket;
/**
* 在创建适配器对象时,必须传入一个新街口的实现类
*/
public SocketAdapter(GBSocketInterface gbSocket) {
this.gbSocket = gbSocket;
}
/**
* 将对就接口的调用适配到新接口
*/
@Override
public void powerWithTwoRound() {
gbSocket.powerWithThreeFlat();
}
}
在适配器中,继承了旧接口,组合了新接口。在重写旧接口方法的时候,调用了新接口的功能。
hotel.setSocket(socketAdapter);
hotel.charge();
在hotel的charge()方法中,调用的是DBSocketInterface 实现子类的两孔充电方法。而这个实现子类,就是适配器类,重写的调用三孔充电的方法。
这也是适配器模式魅力:
不改变原有接口(德标),却还能使用新接口的功能(国标)。
适配器详情和实际使用例子参考《http://blog.csdn.net/zhangjg_blog/article/details/18735243》
03. Java IO 设计模式
1. I/O库对称性
- 输入-输出对称:比如InputStream和OutputStream对Byte字节流的输入和输;而Reader和Writer各自占据Char字符流的输入和输出。
- byte-char对称:InputStream和Reader的子类分别负责byte和字符流的输入;OutputStream和Writer的子类分别负责byte和字符流的输出。
2.两个设计模式
- 装饰模式:在由InputStream、OutputStream、Reader和Writer代表的等级结构内部,有一些流处理器可以对另一些流处理器起到装饰作用,形成新的、具有改善了的功能的流处理器。
- 适配器模式:在由InputStream、OutputStream、Reader和Writer代表的等级结构内部,有一些流处理器是对其他类型的流处理器的适配。这就是适配器的应用。
3.装饰模式的应用
由于java I/O库需要很多性能的各种组合,如果这些性能都是用继承来实现,那么每一种组合都需要一个类,大量重复类。
首先,需要理解java I/O库是由一些原始流处理器和围绕它的装饰流处理器(装饰器,动态扩展原始类性能)所组成的。
这里以InputStream为例,并附上结构图。

这些流类分成两种,即原始流类(Original Stream)和链接流处理器(Wrapper Stream)。
原始流处理器
原始流处理器接收一个Byte数组对象,String对象,FileDiscriptor对象或者不同类型的流源对象,原始流处理器包括以下四种:
- ByteArrayInputStream:接收一个Byte数组作为流的源。
- FileInputStream:建立一个与文件有关的输入流。接收一个File对象作为流的源。
- PipedInputStream:可以与PipedOutputStream配合使用,用于读入一个数据管道的数据,接收一个PipedOutputStream作为源。
- StringBufferInputStream:将一个字符串缓冲区转换为一个输入流。(废弃)
链接流处理器
所谓链接流处理器,就是可以接收另一个流对象作为源,并对之进行功能扩展的类。InputStream类型的链接处理接收另一个InputStream对象作为流源。
以FilterInputStream过滤输入流的子类为例。它将另一个输入流作为流源。这个类的子类包括以下几种:
- BufferedInputStream:用来从硬盘将数据读入到一个内存缓冲区中,并从缓冲区提供数据。
- DataInputStream:提供基于多字节的读取方法,可以读取原始类型的数据。
- LineNumberInputStream:提供带有行计数功能的过滤输入流。
- PushbackInputStream:提供特殊的功能,可以将已经读取的字节“推回”到输入流中。
原始流,就是装模式中具体构件角色(被装饰者),链接流,就是装饰模式中的装饰角色。
抽象结构图

一句话总结:链接流处理器,接收原始流处理器并将其作为成员变量引用,都继承了相同的抽象类InputStream。他们在内部工作方法中做了相应改变,在链接流的相同方法中扩展原始流中的方法,这种变化就是装饰模式的目的。
4.适配器模式的应用
StringBufferInputStream是一个适配器类,其继承了InputStream类型,同时持有一个对String类型的引用。这是将处理String对象的新接口适配成InputStream的旧接口的适配器模式。

其余OutputStream、Reader和Writer的装饰模式和适配器模式
参考《http://www.cnblogs.com/wxgblogs/p/5649933.html》
和《http://www.cnblogs.com/heartstage/p/3391070.html》
Java IO设计模式(装饰模式与适配器模式)的更多相关文章
- Java IO设计模式
JAVA IO 设计模式彻底分析 2011-01-06 14:20:09| 分类: java|字号 订阅 http://blog.csdn.net/tianyue168/archive/2010/0 ...
- Java IO设计模式彻底分析 (转载)
一.引子(概括地介绍Java的IO) 无论是哪种编程语言,输入跟输出都是重要的一部分,Java也不例外,而且Java将输入/输出的功能和使用范畴做了很大的扩充.它采用了流的 机制来实现输入/输出,所谓 ...
- Java程序设计模式系列之适配器模式
理解适配器设计模式需要从生活中的场景进行联系,在生活当中有那些东西能够称为适配器呢?从字面上理解,"适配"的意思就是让一个东西和另一个东西配对,能够让他们一起工作,比如大家用的笔记 ...
- java常用设计模式六:适配器模式
一.定义 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作.比如以下的场景: 用手机充电为例,有一个手机的插孔是TypeC口,现在只 ...
- Java描述设计模式(07):适配器模式
本文源码:GitHub·点这里 || GitEE·点这里 一.适配器模式简介 1.基础概念 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在 ...
- JAVA IO 序列化与设计模式
➠更多技术干货请戳:听云博客 序列化 什么是序列化 序列化:保存对象的状态 反序列化:读取保存对象的状态 序列化和序列化是Java提供的一种保存恢复对象状态的机制 序列化有什么用 将数据保存到文件或数 ...
- java.io包下适配和装饰模式的使用
如java.io.LineNumberInputStream(deprecated),是装饰模式(decorate)的实现: 如java.io.OutputStreamWriter,是适配器模式(ad ...
- java常用设计模式总览
一.java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组 ...
- Java IO流学习
Java IO流学习 Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是 ...
随机推荐
- how to install Web logic Server (WLS)
a) Download artificts from: http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main ...
- 再谈PHP错误与异常处理
博客好久没有更新了,实在惭愧,最近在忙人生大事,哈哈!这段时间没有看什么新的东西,结合项目中遇到的PHP异常处理问题,我又重新梳理了之前模糊的概念,希望对大家理解PHP异常处理有所帮助. 请一定要注意 ...
- socket.io搭配pm2(cluster)集群解决方案
socket.io与cluster 在线上系统中,需要使用node的多进程模型,我们可以自己实现简易的基于cluster模式的socket分发模型,也可以使用比较稳定的pm2这样进程管理工具.在常规的 ...
- 隐马尔科夫模型HMM(一)HMM模型
隐马尔科夫模型HMM(一)HMM模型基础 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数(TODO) 隐马尔科夫模型HMM(四)维特比 ...
- iOS中动态注入JavaScript方法。动态给html标签添加事件
项目中有这样一种需求,给html5网页中图片添加点击事件,并且弹出弹出点击的对应的图片,并且可以保持图片到本地 应对这样的需求你可能会想到很多方法来实现. 1. 最简单的方法就是在html5中添加图片 ...
- Spring+SpringMVC+MyBatis深入学习及搭建(九)——MyBatis和Spring整合
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6964162.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(八)--My ...
- Java web中常见编码乱码问题(二)
根据上篇记录Java web中常见编码乱码问题(一), 接着记录乱码案例: 案例分析: 2.输出流写入内容或者输入流读取内容时乱码(内容中有中文) 原因分析: a. 如果是按字节写入或读取时乱码, ...
- 机器学习:线性判别式分析(LDA)
1.概述 线性判别式分析(Linear Discriminant Analysis),简称为LDA.也称为Fisher线性判别(Fisher Linear Discriminant,FLD) ...
- 快来领取一场专门讲解UTF-8与UTF-16编码算法的GitChat活动的免费名额
微信扫一扫,可打开该GitChat活动页面 字符编码是计算机世界里最基础.最重要.最令人困惑的一个主题之一.不过,在计算机教材中却往往浮光掠影般地草草带过,甚至连一本专门进行深入介绍的专著都找不到(对 ...
- MongoDB--数据库管理
<strong>1.mongod 启动项注释(默认不能生成路径,需手动建立)</strong><br /><span style="white-sp ...