单例模式

单例设计模式是我学到的第一个设计模式。之前我面试时,别人问我”你知道任何设计模式吗?”,我快速的回答说”我知道单例设计模式”,然后继续问到”你知道除了单例模式之外的其他模式吗?”,然后我就哑然了。

Java初学者都知道单例设计模式。至少他会认为他知道单例模式。单例模式的定义甚至比牛顿第三定律。那么单例模式有什么特殊点呢。它简单和直接吗?难道甚至需要一整篇文章来介绍它吗?你相信你100%了解单例设计模式吗?如果你相信,那么请从头读到尾,我相信你会有所发现的。

单例设计模式的定义中只有两个关键点:

1. 对一个类只应该有一个实例,并且

2. 我们需要全局的访问点来访问这个单一的实例

GOF说”确保类只有一个实例,并提供对它的全局访问点【GoF p127】”。

关键点不是问题和定义。在单例模式中,关键部分是实现和管理这个单一的实例。这两点看上去简单,但是实现起来比较困难。是的,很难确保”单一实例”规则和给出灵活的API、很多灵活的访问实例的方法。

实现非常特定于你所使用的编程语言。因此单例模式的安全性也非常特定于实现所使用的语言。

单例实例创建策略

我们限制构造方法并且不允许该类的一个单独的实例。但是我们在相同的类中定义该类的属性并创建和返回它。工厂设计模式可以用于创建单例实例。

package net.traininginjava.designpattern.sample;

public class Singleton {

        private static Singleton instance;

        private Singleton() {

        }

        public static Singleton getInstance() {
                if(instance == null) {
                        synchronized (Singleton.class) {
                                if (instance == null) {
                                        instance = new Singleton();
                                }
                        }
                }
                return instance;
        }
}

在多线程环境中需要特别注意。如果你不同步返回实例的方法,那么在多线程场景下有可能允许多个实例返回。基于性能方面考虑,同步时在块级同步而不是在方法级。在上面的单例模式示例中,你可以看到它是线程安全的。

单例模式中的早初始化还是延迟初始化

上述代码示例中,单例模式使用了延迟初始化方式。唯一的实例将在第一次调用getInstance方法时被创建。我们也可以用简单的方式来实现相同的单例设计模式,只是在加载该类时就实例化该单例实例。下面的实例展示了如何在早期来初始化该实例。同样也照顾到了多线程场景。

package net.traininginjava.designpattern.sample;

package net.traininginjava.designpattern.sample;

public class Singleton2 {
        private static Singleton2 instance = new Singleton2();
        private Singleton2() {}
        public static Singleton2 getInstance() {
                return instance;
        }
}

单例和序列化

使用序列化,单例模式与单例模式之间存在冲突。你可以序列化然后反序列化来获取新的相同的单例模式的类的实例。使用Java API,你可以实现如下的方法并从流中读取来覆盖实例。你可以确保总是有一个唯一的实例。

ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

这篇文章主要是想解释单例设计模式的基本知识。如果你希望在读完本文章后对单例设计模式有更深入的了解,你可以读这篇文章”When is a Singleton not a Singleton?“。

Java API中的单例模式

java.lang.Runtime#getRuntime() java.awt.Desktop#getDesktop()

此条目发表在 设计模式 分类目录,贴了 , 标签。将固定链接加入收藏夹。

单例模式》有 1 条评论

  1. Pingback 引用通告: Java面试时常见的10个问题 | Java视点

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>