今天复习了一下设计模式,也从源码中去寻找了一下设计模式在JDK中的运用。
适配器模式:
核心思想就是将一个接口适配(伪装成)到另一个接口。在Java I/O中运用到了很多适配器模式,例如将字符串数据转变成字节数据保存到文件中或将字节数据转变成流数据等,下面用InputStreamReader 举例。
public class InputStreamReader extends Reader {//适配器类InputStreamReader继承于目标接口类
private final StreamDecoder sd;//用JVM转码的过程,用于将字节转为字符
/**
* Creates an InputStreamReader that uses the default charset.
*
* @param in An InputStream
*/
public InputStreamReader(InputStream in) {//可以看到构造参数是InputStream,这就是适配器的核心
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}
}
从上面可以看出,适配器类InputStramReader 继承于目标抽象类Reader,在下面的构造参数中可以看到是怎么将源抽象类InputStram 转换成 Reader需要的字节的,用的是streamDecoder。 这样看来大体结构就已经很清晰了:
InputStramReader是适配器类,用于将InputStram 字符流转换成 Reader需要的字节流。
Reader:目标抽象类,即为需要转换的目标。
InputStram:源目标抽象类,即需要被转换的目标。
工厂模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
例如在 java.util.Calendar 中的getInstance()方法就使用了简单工厂模式。
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {//LocaleProviderAdapter.getAdapter中的反射机制得到aLocale然后根据aLocale 返回不同的对象
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {//和上面思想一致
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
上面源码中可以看出LocaleProviderAdapter.getAdapter中使用反射机制得到aLocale然后根据aLocale 返回不同的对象。是一个标准的工厂模式使用。
装饰者模式:动态地给一个对象添加一些额外的功能。
装饰者模式可以动态的给类提供额外的功能,通常又一个装饰类,装饰实现类,然后抽象装饰类继承于需要被装饰的类。
例如在继承于InputStream的FilterInputStream就是装饰类,而DataInputStream,BufferedInputStream,PushBackInputStream都继承于装饰类 FilterInputStream,作为装饰实现类; 为被装饰的类InputStream提供额外的功能。例如BufferedInputStream 就提供了缓存功能。下面是伪代码:
public class FilterInputStream extends InputStream {}//装饰类
public class BufferedInputStream extends FilterInputStream {}//装饰实现类
//具体实现忽略
吃午饭去了,下次继续更新。。