设计模式学习笔记--设计模式在Java I/O中的应用(装饰模式和适配器模式)(一)

2014-11-23 23:31:15 · 作者: · 浏览: 3


写在模式学习之前


什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式;每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案;当我们碰到模式所描述的问题,就可以直接用相应的解决方法去解决这个问题,这就是设计模式。

设计模式就是抽象出来的东西,它不是学出来的,是用出来的;或许你根本不知道任何模式,不考虑任何模式,却写着最优秀的代码,即使以“模式专家”的角度来看,都是最佳的设计,不得不说是“最佳的模式实践”,这是因为你积累了很多的实践经验,知道“在什么场合代码应该怎么写”,这本身就是设计模式。

有人说:“水平没到,学也白学,水平到了,无师自通”。诚然,模式背熟,依然可能写不出好代码,更别说设计出好框架;OOP理解及实践经验到达一定水平,同时也意味着总结了很多好的设计经验,但"无师自通",却也未必尽然,或者可以说,恰恰是在水平和经验的基础上,到了该系统的学习一下“模式”的时候了,学习一下专家总结的结果,印证一下自己的不足,对于提高水平还是很有帮助的。

本系列的设计模式学习笔记,实际是对于《Java与模式》这本书的学习记录。


Java I/O库的设计原则


在Java 语言I/O库的设计中,使用了两个结构模式,即装饰模式和适配器模式。本篇围绕这两个模式讨论Java I/O库的设计。


Java库的两个对称性


(1)输出-输入对称:处理Byte流的InputStream和OutputStream;处理Char流的Reader和Writer。

(2)byte-char对称:InputStream与Reader的子类分别负责Byte和Char的输入;OutputStream与Writer的子类分别负责Byte和Char流的输出,它们分别形成平行的等级结构。


Java库的两个设计模式


(1)装饰模式:装饰模式在Java语言中的最著名的应用莫过于Java I/O标准库的设计了。

(2)适配器模式:适配器模式是Java I/O库中第二个最重要的设计模式。


装饰模式的应用


InputStream类型中的装饰模式


结构图:

\

装饰模式的各个角色:

(1)抽象构件(Component)角色:由InputStream扮演。这是一个抽象类,为各种子类型流处理器提供统一的接口。

(2)具体构件(ConcreteComponent)角色:由ByteArrayInputStream、FileInputStream、PipedInputStream以及StringBufferInputStream等原始流处理器扮演。他们实现了抽象构件角色所规定的接口,可以被链接流处理器所装饰。

(3)抽象装饰(Decorator)角色:由FilterInputStream扮演。它实现了InputStream所规定的接口。

(4)具体装饰(ConcreteDecorator)角色:由几个类扮演,分别是DataInputStream、BufferInputStream以及两个不常用的类LineNumberInputStream和PushBackInputStream

注意:StringBufferInputStream、LineNumberInputStream已经过时,不再推荐使用。

OutputStream类型中的装饰模式


结构图:

\

装饰模式的各个角色:

(1)抽象构件(Component)角色:由OutputStream扮演。这是一个抽象类,为各种的子类型流处理器提供统一的接口。

(2)具体构件(ConcreteComponent)角色:由ByteArrayOutputStream、FileOutputStream以及PipedOutputStream等扮演,它们均实现了OutputStream所声明的接口。

(3)抽象装饰(Decorator)角色:由FilterOutputStream扮演。它有与OutputStream相同的接口,而这正是装饰类的关键。

(4)具体装饰(ConcreteDecorator)角色:由几个类扮演,分别是BufferedOutputStream、DataOutputStream,以及PrintStream。


Reader类型中的装饰模式


结构图:

\

装饰模式的各个角色:

(1)抽象构件(Component)角色: 由Reader扮演。这是一个抽象类,为各种的子类型流处理器提供统一的接口。

(2)具体构件(ConcreteComponent)角色:有CharArrayReader、InputStreamReader、PipedReader以及StringReader等扮演,它们均实现了Reader所声明的接口。

(3)抽象装饰(Decorator)角色:由BufferedReader以及FilterReader扮演。这两者有着与Readeer相同的接口,而这正是装饰类的关键。

(4)具体装饰(ConcreteD)角色:分别是LineNumberReader作为BufferedReader的具体装饰角色,PushbackReader作为FilterReader的具体装潢角色。


Writer类型中的装饰模式


结构图:

\

装饰模式的各个角色:

(1)抽象构件(Component)角色:由Writer扮演。这是一个抽象类,为各种的子类型流处理器提供统一的接口。

(2)具体构件(ConcreteComponent)角色:由CharArrayWriter、OutputStreamWriter、PipedWriter以及StringWriter等扮演,它们均实现了Reader所声明的接口。

(3)抽象装饰(Decorator)角色:由BufferedWriter、FilterWriter以及PrintWriter扮演,它们有着与Writer相同的接口。

(4)具体装饰(ConcreteDecorator)角色:是与抽象装饰角色合并的。由于抽象装饰角色与具体装饰角色发生合并,因为装饰模式在这里被简化了。


装饰模式和适配器模式的对比


(1)装饰模式和适配器模式,都是通过封装其他对象达到设计目的的。

(2)理想的装饰模式在对被装饰对象进行功能增强时,要求具体构件角色、装饰角色的接口与抽象构件角色的接口完全一致;而适配器模式则不然,一般而言,适配器模式并不要求对源对象的功能进行增强,只是利用源对象的功能而已,但是会改变源对象的接口,以便和目标接口相符合。

(3)装饰模式有透明和半透明两种,区别就在于接口是否完全一致。关于装饰模式的重要的事实是,很难找到理想的装饰模式。一般而言,对一个对象进行功能增强的同时,都会导致加入新的行为,因此,装饰角色的接口比抽象构件角色的接口宽是很难避免的,这种现象存在于Java I/O库中多有的类型的链接流处理器中。一个装饰类提供的新的方法越多,它离纯装饰模式的距离就越远,离适配器模式的距离也就越近。


适配器模式的应用


InputStream原始流处理器中的适配器模式


ByteArrayInputStream是一个适配器类:\


FileInputStream是一个适配器类:\


StringBufferInputStr