There are many objects we only need one of: thread pools, caches, dialog boxes, objects that handle preferences and registry settings, objects used for logging, and objects that act as device drivers to devices like printers and graphics cards. In fact, for many of these types of objects, if we were to instantiate more than one we'd run into all sorts of problems like incorrect program behavior, overuse of resources, or inconsistent results.
有一些对象我们只需要一个:线程池、缓存、对话框、偏好处理和注册表设置对象、日志对象、充当打印机、显卡等设备的驱动程序的对象。事实上,很多这类型的对象,如果我们实例化多个会导致各种问题,比如:程序的异常行为、资源的过量使用、或者不一致的结果。
(来源于《Head First Design Pattern》 P170)
Definition: The Singleton Pattern ensures a class has only one instance, and provides a global point of access to it.
(来源于《Head First Design Pattern 》P177)
如何创建单例模式:懒汉式、饿汉式
1) 构造方法私有化
2)在类的内部创建对象
3)创建一个静态的公有的方法,返回实例化了的单例。
懒汉式
用同步去处理多线程,防止创建两个对象,但同步会降低性能,同步一个方法会使性能下降100倍
范例:(感觉自己的程序很好吃)
饿汉式 :Move to an eagerly created instance rather than a lazily created one 急切创建实例,而非延迟创建
范例:(灵感来自于每天上课饿了)
扩展一:Use "double-checked looking" to reduce the use of synchronization in getInstance()
使用“双重检查加锁”去减少在getInstance()中使用同步
We first check to see if an instance is created, and if not, then we synchronize. This way, we only synchronize the first time through.
首先检查实例是否已经创建,如果没有创建,才使用同步。这样,我们只有在第一次才会使用到同步。
public class Singleton(){
privatevolatile static Singleton uniqueInstance;
private Singleto(){}
public static Singleton getInstance(){
//检查实例,如果不存在,就进入同步区
if(uniqueInstance == null){
//只有第一次才彻底执行这里的代码
synchronized (Singleton.class){
//进入同步区后再检查一次,若仍为null,才创建实例
if(uniqueInstance == null)
uniqueInstance = new Singleton();
}
}
return uniqueInstance;
}
}
The volatile keyword ensure that multiple threads handle the uniqueInstance variable correctly when it is being initialized to the Singleton instance.
volatile关键字确保,当uniqueInstance变量实例化单例时,多个线程能正确地处理uniqueInstance变量。
(来源于《Head First Design Pattern 》P182)
扩展二:volatile关键字
扩展三:框架中的单例模式
1.Struts2中的Action是多例的而非单例,一个Session产生一个Action,每一次请求产生一个Action。
原因:因为Struts2中的Action存放着数据,好比在页面填写表单数据时,数据可以以Action属性传输的方式传送到后台。若Action为单例,在多线程的情况下会造成数据的传输错误或泄露。但有的Action规定只能由Admin使用,这时就可以将Action设为单例。
2.Spring的IOC容器管理的bean默认是单例的,但在配置Action bean时,可以通过配置scope来设定是单例或是多例。