您的位置:首页 > 编程语言 > Java开发

装饰者模式在Java I/O中的应用

2016-06-10 15:01 786 查看
首先来说说什么是装饰者模式,装饰责模式的主要就是动态地给一个对象添加一些额外的职责或者行为。这种方式比继承来的更加的灵活,下面的他的各个组件关系图。



分析一下各个组件:

Component(抽象组件角色):-被装饰对象的统一接口

ConcreteComponent(具体组件角色):-被装饰者

Decorator(抽象装饰器):-维持一个指向构件Component对象的实例

ConcreteDecorator(具体装饰器角色): -添加职责

其实这样看还是很抽象的,下面就借用JDK中的关于这个模式的应用,在Java I/O中就应用了装饰者设计模式,来看一下类图结构。



可以看到输入流有一个共同的基类,就是InputStream这个类在这个模式中扮演了Component的角色。

来看一下一个简化图吧~



可以看到这个FilterInputStream的类是非常重要的,下面是部分代码

public
class FilterInputStream extends InputStream {
/**
* The input stream to be filtered.
*/
protected volatile InputStream in;

/**
* Creates a <code>FilterInputStream</code>
* by assigning the  argument <code>in</code>
* to the field <code>this.in</code> so as
* to remember it for later use.
*
* @param   in   the underlying input stream, or <code>null</code> if
*          this instance is to be created without an underlying stream.
*/
protected FilterInputStream(InputStream in) {
this.in = in;
}


可以看到这个类继承了一个InputStream,还聚合了一个InputStream,他的构造方法会传入一个InputStream这个类的作用就是装饰传来的输入流,看类的结构可以看出来继承FilterInputStream的类都是装饰类,他们数据的来源的别的输入流。

其实整个装饰者的思想就是用一些小部件来装饰一样东西,在生活中非常常见,比如说买咖啡的时候,一般先是一个普通的咖啡,你可以选择向里面添加糖或者牛奶或者冰块或者一些其他的东西,如果我们在设计一群这样类的时候采用继承的方式,每添加一个配料都要添加无数个种类的类,这样简直的类爆炸,所以我们会采用装饰者设计模式,用配料去装饰基类。实现方式就是上面类图中所描绘的。

下面我简单实现了一个自己功能的装饰流,



CharFilterInputStream类就是我们自己实现的,主要功能是过滤特殊字符的输入流,来看一下这个类的代码

package com.ls;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
* 过滤特殊字符的输入流,默认过滤数字
* @author LiuShuai
*
*/
public class CharFilterInputStream extends FilterInputStream {
//默认过滤的字符串
private static final char[] DEFAULT_CHARS = {'1','2','3','4','5','6','7','8','9','0'};
//过滤的字符串
private static char[] filterChars = null;

public CharFilterInputStream(InputStream in) {
this(in, DEFAULT_CHARS);
}

public CharFilterInputStream(InputStream in,char[] cs){
super(in);
filterChars = cs;
}

@Override
public int read(byte[] b, int off, int len) throws IOException {

if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}

int n = 0;

int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
if (filterChar((char)c)) {
n++;
}

int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
if (filterChar((char)c)) {
n++;
}
b[off + i] = (byte)c;

}
} catch (IOException ee) {
}
byte[] bs = new byte
;
n=0;
//这里进行字符串的过滤
for (int j = 0; j < b.length; j++) {
byte d = b[j];
if (filterChar((char)d)) {
bs[n++] = d;
}
}
//这里是把过滤的字符串变成空格,而且把中间的空格去掉,其实是移到了最后面
for (int j = 0; j < b.length; j++) {
if (j<bs.length) {
b[j] = bs[j];
}else {
b[j] = ' ';
}
}

return i;

}

/**
* 过滤某个字符
* @param c
* @return
*/
private boolean filterChar(char c){
boolean flag = false;
for(char c1 : filterChars){
if (c1 == (char)c) {
flag = true;
break;
}
}
return flag;
}

}


下面是测试类:

public class Test {

public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
CharFilterInputStream charFilterInputStream =
new CharFilterInputStream(new StringBufferInputStream(input));

BufferedReader reader = new BufferedReader(new InputStreamReader(charFilterInputStream));
System.out.println(reader.readLine());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: