单例模式
单例是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
问题
当你希望控制某些共享资源、状态变量或者访问权限时,你会希望某些类的实例数量仅能为一个;或者当你希望可以在系统全局的任意位置去访问同一个实例。
解决方案
使用单例模式,单例模式会禁止类从外部主动创建实例,而是通过公开的静态方法对外提供唯一的一个实例,你可以在全局的任意位置去获取都它。
优点
- 你可以保证一个类只有一个实例。
- 你获得了一个指向该实例的全局访问节点。
- 仅在首次请求单例对象时对其进行初始化。
缺点
- 单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等。
- 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。
模式结构图
实现
完整代码地址
懒汉式
懒汉式指在类被加载时不主动创建实例,只有在外部第一次调用获取实例的接口时才进行实例的创建。优点是不需要使用时不会占用资源,缺点是可能会引起多线程安全问题。代码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class SingletonLazy { private static SingletonLazy mInstance;
private SingletonLazy() {
}
public static SingletonLazy getInstance() { if (mInstance == null) { mInstance = new SingletonLazy(); } return mInstance; }
public void printMsg() { System.out.println("Hello World!"); } }
|
饿汉式
饿汉式指在类加载时就创建好应用实例,优点是提前做好实例创建取用较快,没有线程安全问题,缺点是不使用时也会占用资源。代码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class SingletonHungry { private static SingletonHungry mInstance = new SingletonHungry();
private SingletonHungry() {
}
public static SingletonHungry getInstance() { return mInstance; }
public void printMsg() { System.out.println("Hello SingletonHungry!"); }
}
|
懒汉式–双重检查的最佳实践
既实现懒加载又确保线程安全的单例写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class SingletonDoubleCheck { private volatile static SingletonDoubleCheck mInstance;
private SingletonDoubleCheck() { }
public static SingletonDoubleCheck getInstance() { if (mInstance == null) { synchronized (SingletonDoubleCheck.class) { if (mInstance == null) { mInstance = new SingletonDoubleCheck(); } } } return mInstance; }
public void printMsg() { System.out.println("Hello SingletonDoubleCheck!"); }
}
|
适用场景
- 如果程序中的某个类对于所有客户端只有一个可用的实例,可以使用单例模式。
- 如果你需要更加严格地控制全局变量/资源等,可以使用单例模式。