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乐园

有用!分享+在看☟

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BUG弄潮儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值