单例模式的实现与使用
单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
通常单例模式在Java语言中,有两种构建方式:
- 饿汉方式。指全局的单例实例在类装载时构建。
public class Singleton { private final static Singleton INSTANCE = new Singleton(); // Private constructor suppresses private Singleton() {} // default public constructor public static Singleton getInstance() { return INSTANCE; } }
- 懒汉方式。指全局的单例实例在第一次被使用时构建。
public class Singleton { private static volatile Singleton INSTANCE = null; // Private constructor suppresses // default public constructor private Singleton() {} //thread safe and performance promote public static Singleton getInstance() { if(INSTANCE == null){ synchronized(Singleton.class){ //when more than two threads run into the first null check same time, to avoid instanced more than one time, it needs to be checked again. if(INSTANCE == null){ INSTANCE = new Singleton(); } } } return INSTANCE; } }
这两种实现方式在使用时有何不同呢?考虑两点:
- 在获取单例对象时,饿汉方式可以直接返回一个在类装载时即创建好的单实例对象,而懒汉方式则需要先判断是否已经存在单例对象,如果存在则直接返回已有对象,否则创建新的的对象返回。此时,需要特别注意的是:在多线程条件下,需要足够的手段保证实例没有被多次创建。
- 饿汉方式在类装载时即创建单例对象,这意味着程序无法在运行过程中根据特定的条件创建不同类型的对象,而懒汉模式配合工厂模式则可以实现以上要求。
以上第二点是在面试时被问到的一个问题的回答,面试官还提到在实际的工程中要想实现真正的单例其实是很困难的,因此我又搜索的一些资料,发现http://calmness.iteye.com/blog/60179 有完整的解答,稍后有空再整理归纳出来。