适配器模式(Adapter Pattern)的主要作用是在新接口和老接口之间进行适配,不改变原有接口,却还能使用新接口的功能。
Java IO 中的从字节流到字符流的转换就用了适配器模式实现。
示例如下:
/**
* 英语口语规范
*
* @author lslxy1021
*/
interface EnglishSpecification {
void sayEnglish();
}
/**
* 英语口语
*
* @author lslxy1021
*/
class English implements EnglishSpecification {
@Override
public void sayEnglish() {
System.out.println("I can say English!");
}
}
/**
* 到以英语为母语的国家需要说英语
*
* @author lslxy1021
*/
class Speak {
private EnglishSpecification language;
public Speak(EnglishSpecification language) {
this.language = language;
}
public void speak() {
language.sayEnglish();
}
}
/**
* 汉语口语规范
*
* @author lslxy1021
*/
interface ChineseSpecification {
void sayChinese();
}
/**
* 汉语口语
*
* @author lslxy1021
*/
class Chinese implements ChineseSpecification {
@Override
public void sayChinese() {
System.out.println("我能说汉语!");
}
}
/**
* 语言适配器
*
* @author lslxy1021
*/
class LanguageAdapter implements EnglishSpecification {
private ChineseSpecification language;
public LanguageAdapter(ChineseSpecification language) {
this.language = language;
}
@Override
public void sayEnglish() {
language.sayChinese();
}
}
/**
* 适配器测试
*
* @author lslxy1021
*/
public class AdapterTest {
public static void main(String[] args) {
Speak speakEnglish = new Speak(new English());
speakEnglish.speak();
//实现英语口语与汉语口语的适配
LanguageAdapter adapter = new LanguageAdapter(new Chinese());
Speak speakChinese = new Speak(adapter);
speakChinese.speak();
}
}
输出结果:
I can say English!
我能说汉语!
适配器的重点在于通过一个适配器类实现了新旧接口间的兼容,适配器类实现了旧的接口,并在其中调用了新接口的方法。
Java中字节流与字符流的转换与此类似,示例如下:
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("d:/test.txt")));
Java IO中的适配器
Java IO 库中大量使用了适配器模式。InputStream、OutputStream、Reader、Writer 类的原始流处理器(不包括装饰类)都可以看做是适配器模式的应用。
以 ByteArrayInputStream 为例,它将一个 byte 数组的接口适配成 InputStream 流处理器的接口。
public class ByteArrayInputStream extends InputStream {
protected byte buf[];
protected int pos;
protected int mark = 0;
protected int count;
public ByteArrayInputStream(byte buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
public ByteArrayInputStream(byte buf[], int offset, int length) {
this.buf = buf;
this.pos = offset;
this.count = Math.min(offset + length, buf.length);
this.mark = offset;
}
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
if (pos >= count) {
return -1;
}
int avail = count - pos;
if (len > avail) {
len = avail;
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
public synchronized long skip(long n) {
long k = count - pos;
if (n < k) {
k = n < 0 ? 0 : n;
}
pos += k;
return k;
}
public synchronized int available() {
return count - pos;
}
public boolean markSupported() {
return true;
}
public void mark(int readAheadLimit) {
mark = pos;
}
public synchronized void reset() {
pos = mark;
}
public void close() throws IOException {
}
}