JDK源码解读单例模式与工厂模式
0x01:单例模式
java.lang.Runtime
public class Runtime {
//单例成员变量
private static Runtime currentRuntime = new Runtime();
//获取单例
public static Runtime getRuntime() {
return currentRuntime;
}
//私有构造方法
private Runtime() {}
//省略 .....
}
从源码看标准的饿汉模式,Runtime类封装了Java运行时的环境。每一个java程序实际上都是启动了一个JVM进程,那么每个JVM进程都是对应这一个Runtime实例,此实例是由JVM为其实例化的。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
在Java的GUI编程接口上也有几个单例模式的实现,但是Java的GUI编程在国内几乎被淘汰了,这里就不介绍了。
0x02:工厂模式
java.util.Calendar
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
public static Calendar getInstance(TimeZone zone,
Locale aLocale){
return createCalendar(zone, aLocale);
}
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
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;
}
}
}
if (cal == null) {strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
//省略......
}
分析源码可以知道Calendar使用了简单工厂模式,通过getInstance()方法进去,而getInstance()方法调用了createCalendar()方法。
javax.xml.parsers.DocumentBuilderFactory
public static DocumentBuilderFactory newInstance() {
return FactoryFinder.find(
DocumentBuilderFactory.class,
"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
}
public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader){
return FactoryFinder.newInstance(DocumentBuilderFactory.class,
factoryClassName, classLoader, false);
}
public abstract DocumentBuilder newDocumentBuilder()
throws ParserConfigurationException;
javax.xml.parses包的DocumentBuilderFactory用于创建DOM模式的解析器对象,DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
从DocumentBuilderFactory源码上看提供了一个默认的实现DocumentBuilderFactoryImpl.java,看到该类的newDocumentBuilder,可以看出只要调用newInstance()方法就会返回一个新的DocumentBuilder 对象
public DocumentBuilder newDocumentBuilder()
throws ParserConfigurationException
{
if (grammar != null && attributes != null) {
if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_LANGUAGE)) {
throw new ParserConfigurationException(
SAXMessageFormatter.formatMessage(null,
"schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_LANGUAGE}));
}
else if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_SOURCE)) {
throw new ParserConfigurationException(
SAXMessageFormatter.formatMessage(null,
"schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_SOURCE}));
}
}
try {
return new DocumentBuilderImpl(this, attributes, features, fSecureProcess);
} catch (SAXException se) {
throw new ParserConfigurationException(se.getMessage());
}
}
扫码二维码
获取更多精彩
Java乐园