前言
在之前的博客——《装饰者模式(Decorator Pattern)——给爱用继承的人一个全新的设计眼界》学习了装饰模式,但是也只是一知半解,连java中使用装饰者设计模式最典型的InputStream家族都没指出,似乎有点水了点。所以,在这里做一个补充。
还记得如何从一个控制台读取一行字符串吗?
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( System.in ) );
try {
System.out.println( bufferedReader.readLine());
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
在java IO中,这种形式new xx(new xxx(new xxxx( new xxxxxx())))似乎很常见。事实上,他们都来继承自抽象类InputStream。下面将简单介绍一下InputStream。
类图
- InputStream: 这是一个抽象类,相当于装饰者模式中的超类。在这个抽象类中只有一个抽象方法read(),也就是一定要用子类去实现的。不过别的函数会调用这个方法。所以,InputStream的所有子类都必须实现read()。
- FileInputStream、ByteArrayInputStream、StringBufferedInputStream等:相当于装饰者模式的具体组件。实现自InputStream。
- FilterInputStream:抽象装饰者类。继承InputStream。
- BufferedInputStream、DataInputStream、CheckedInputStream等:具体的装饰类,继承自FilterInputStream。
一些实践
描述:设计一个简单类,在读文件时,将大写字母转化为小写字母,将小写字母转化为大写字母。
思路:在设计时可以通过继承抽象装饰者类(FilterInputStream)来实现一个装饰类。通过调用InputStream类或其他子类提供的一些方
法再加上逻辑判断代码从而可以很简单地实现这个功能。
小插曲:在这中间,写了一个测试类,继承FilterInputStream,输出一段中文字符。
代码实现:
package inputStreamObserver;
import java.io.*;
/**
* <p>ClassName ElogInputStream
* <p>Description
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/8/6 0:27
*/
public class ElogInputStream extends FilterInputStream {
public ElogInputStream(InputStream in) {
super( in );
System.out.println( "Elog.read()-----there will change the style of Character!" );
}
public final int read() throws IOException {
// System.out.println( "Elog.read()-----there will change the style of Character!" );
int c = 0;
if ((c = super.read()) != -1) {
if (Character.isLowerCase( c )) {
//将小写转换为大写
return Character.toUpperCase( c );
} else if (Character.isUpperCase( c )) {
//大写转化成小写
return Character.toLowerCase( c );
} else {
return c;
}
} else {
return -1;
}
}
}
package inputStreamObserver;
import java.io.*;
/**
* <p>ClassName ClogInputStream
* <p>Description
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/8/6 0:27
*/
public class ClogInputStream extends FilterInputStream {
public ClogInputStream(InputStream in) {
super( in );
System.out.println( "Clog.read()----这里输出的是中文" );
}
public int read() throws IOException {
return in.read();
}
}
package inputStreamObserver;
import java.io.*;
/**
* <p>ClassName TestInputStream
* <p>Description
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/8/6 10:24
*/
public class TestInputStream {
public static void main(String[] args) {
File file = new File( "E:/Desktop/test.txt" );
// 大小写互换。
int c = 0;
try {
InputStream inputStream = new ElogInputStream( new FileInputStream( file ) );
while ((c = inputStream.read()) != -1) {
System.out.print( (char) c );
}
inputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println();
//这里是小插曲,开始,请自动忽略
// 重写read,输出一段中文字符。
int num = 0;
try {
InputStream in = new ClogInputStream( new FileInputStream( file ) );
while ((num = in.read()) != -1) {
System.out.print( (char) num );
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
// 小插曲结束
}
}
运行结果