单例模式大概是最直观的一种设计模式了,尽管直观却不简单。
数学与逻辑学中,singleton定义为“有且仅有一个元素的集合”,
单例模式可以如下定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供”。
我比较喜欢Design Patterns 一书中的描述"保证一个类仅有一个实例,并提供一个访问它的全局访问点"。
单例模式的特点
1.单例类只能有一个实例
2.单例类必须自己自己创建自己的唯一实例
3.例类必须给所有其他对象提供这一实例
单例模式的经典实现
实现单例,可以将类的构造方法限定为private,避免在外部实例化,然后在类中提供一个静态的实例并能够返回给使用者,
在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance方法访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
线程安全的实现
经典的实现方法并没有考虑多线程的环境,试想存在两个线程A和B,
同时调用getInstance方法,线程A检查uniqueInstance是null,开始创建实例;
同时线程B检测到uniqueInstance是null,于是线程A/B各自创建了对象。
解决这个问题最简单的方法是加锁,为getInstance的静态方法添加synchronized关键字,
但是考虑到Synchronized同步锁的性能较低,可以调整Synchronized添加(加锁)的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
饿汉式 懒汉式和登记式
另外,一些文档会提到单例模式的三种形式(懒汉式,饿汉式,登记式),
其实饿汉式和懒汉式主要是线程安全的区别,同时懒汉式是延迟加载,
在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建,例如下面代码:
1 2 3 4 5 6 7 8 9 10 11 |
|
懒汉式单例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|