- 意图:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。 - 动机:
- 适用性:
a. 当类只能有一个实例且客户可以从一个众所周知的访问点访问它时。
b. 当这个唯一实例应该是通过子类化可拓展的,并且客户应该无需更改代码就能使用一个扩展的实例时。 - 结构:
-
参与者:
a. Singleton:
定义一个Instance操作,运行客户访问它的唯一实例。Instance是一个类操作(即C++中的一个静态成员函数和Java中的静态方法)。
可能负责创建它自己的唯一实例。 -
协作:
客户只能通过Singleton的Instance操作访问一个Singleton的实例 -
效果:
a. 对唯一实例的受控访问
b. 缩小名空间
c. 允许对操作和表示的精化
d. 允许可变数目的实例
e. 比类操作更灵活 -
实现:
a.保证一个唯一的实现
b. 创建Singleton类的子类 -
代码示例:
/** * 饿加载方式 * 静态变量创建对象 */ public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } } /** * 饿加载方式 * 静态代码块中给对象赋值 */ public class Singleton { private static Singleton instance; static { instance = new Singleton(); } private Singleton() {} public static Singleton getInstance() { return instance; } } /** * 饿加载式 * 枚举类: 由Java的语法糖保证线程的安全性 */ public enum Singleton { INSTANCE; public void singletonOperation() { } public void getSinletonData() { } } /** * 懒加载式 * 双重检查锁 */ public class Singleton { //volatile 保证在多线程环境多个变量对实例对象的可见性 private static volatile Singleton instance; private Singleton() {} public static Singleton instance() { //加锁前判断实例对象不为空直接返回,意味着已经有其他线程创建了实例对象 if (instance == null) { synchronized (Singleton.class) { //加锁后判断实例对象不为空是为了避免多次创建实例对象 if (instance == null) { instance = new Singleton(); } } } return instance; } } /** * 懒加载式 * 静态内部类 */ public class Singleton { private Singleton() {} /** * 只有在调用getInstance()虚拟机才会加载SingletonHolder类并初始化INSTANCE * 从而保证了懒加载的效果同时也保证了实例对象全局的唯一性 */ private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } //对外提供静态方法获取该对象 public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }
-
已知应用:
-
相关模式:
很多模式可以用Singleton模式实现。例如:Abstract Factory、Builder和Prototype