I/O流的装饰器
分析
Java的IO流粗略架构如下:
Java的IO流就是利用了装饰模式,这在我们平时使用的时候也能感觉出来,每次的输入输出都要一层层的“装饰”才能使用。
为了实现将输入的英文加密后再存储到文本文件里,其实我们可以选择多个装饰的“层”。
我选择了输出流中的 FilterOutputStream进行了装饰,即在接收到了控制台的输入之后,首先进行加密转换,然后再调用基类的方法写入到文件中去。
UML图:
总结:
装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。是继承关系的一个替代方案。
**优点:**装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
- 比静态继承更灵活: 与对象的静态继承(多重继承)相比, Decorator模式提供了更加灵活的向对象添加职责的方式。
- Decorator与它的Component不一样 Decorator是一个透明的包装。
- 避免在层次结构高层的类有太多的特征 Decorator模式提供了一种“即用即付”的方法来添加职责。
**缺点:**多层装饰比较复杂。采用Decorator模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在他们相互连接的方式上有所不同,而不是它们的类或是它们的属性值有所不同。尽管对于那些了解这些系统的人来说,很容易对它们进行定制,但是很难学习这些系统,排错也很困难。
代码:
类图:
1、 装饰类EncryptionEnglish,继承了FilterOutputStream,重写了write方法,实现对写入内容的加密。
package medemede;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
//文件写入过程的装饰类,装饰了FilterOutputStream
public class EncryptionEnglish extends FilterOutputStream {
EncryptionEnglish(OutputStream out) {
super(out);
}
@Override //重写了write方法,对ASCII码循环加2
public void write(int x) throws IOException {
if(x<91){
if(x+2>90)
x=x-26+2;
else
x=x+2;
}else {
if(x+2>122)
x=x-26+2;
else
x=x+2;
}
super.write(x); //调用基类方法写入文件中
}
}
2、 装饰类Decrypted,继承了FileInputStream,重写了read方法,实现对文件内容的解密输出。
package medemede;
import java.io.*;
//文件读取过程的装饰类,装饰了FileInputStream
public class Decrypted extends FileInputStream {
public Decrypted(String name) throws FileNotFoundException {super(name);}
public Decrypted(File file) throws FileNotFoundException {super(file);}
public Decrypted(FileDescriptor fdObj) {
super(fdObj);
}
@Override //重写了read方法,对内容循环减2
public int read() throws IOException {
int x=super.read(); //调用基类方法获取字节
if(x==-1)
return x;
else {
if(x<91){
if(x-2<65)
x=x+24-2;
else
x=x-2;
}else {
if(x-2<97)
x=x+24-2;
else
x=x-2;
}
return x;
}
}
}
3、 客户端,实现加密输入与解密输出
package medemede;
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//从键盘接受字节并写入test.txt
Scanner in=new Scanner(System.in);
OutputStream outputStream=null;
String str;
try {
outputStream=new EncryptionEnglish(new BufferedOutputStream(new FileOutputStream(new File("test.txt"))));
str=in.next();
outputStream.write(str.getBytes());
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
assert outputStream != null;
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//从test.txt中读取数据,并解密输出
FileInputStream fis;
try {
int len;
//调用的原FileInputStream
FileInputStream fisOld=new FileInputStream("test.txt");
System.out.print("文件内的加密内容:");
while ((len = fisOld.read()) != -1) {
System.out.print((char)len);
}
System.out.println();
//调用的装饰类Decrypted
fis = new Decrypted("test.txt");
System.out.print("文件内容解密:");
while ((len = fis.read()) != -1) {
System.out.print((char)len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、 输出