0%

单例模式

单例模式

单例是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。

问题

当你希望控制某些共享资源、状态变量或者访问权限时,你会希望某些类的实例数量仅能为一个;或者当你希望可以在系统全局的任意位置去访问同一个实例。

解决方案

使用单例模式,单例模式会禁止类从外部主动创建实例,而是通过公开的静态方法对外提供唯一的一个实例,你可以在全局的任意位置去获取都它。

优点

  • 你可以保证一个类只有一个实例。
  • 你获得了一个指向该实例的全局访问节点。
  • 仅在首次请求单例对象时对其进行初始化。

缺点

  • 单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等。
  • 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。

模式结构图

实现

完整代码地址

懒汉式

懒汉式指在类被加载时不主动创建实例,只有在外部第一次调用获取实例的接口时才进行实例的创建。优点是不需要使用时不会占用资源,缺点是可能会引起多线程安全问题。代码如下所示

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!");
}

}

适用场景

  • 如果程序中的某个类对于所有客户端只有一个可用的实例,可以使用单例模式。
  • 如果你需要更加严格地控制全局变量/资源等,可以使用单例模式。