设计模式 - 单例模式

单例模式(Singleton mode)

一、概念

采取一定的方法保证在整个软件系统中 ,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

一、应用场景

  • 只需要一个实例
    • 各种 Manager
    • 各种 Factory

三、设计模式写法(八种)

1.饿汉式 (静态常量)

1
2
3
4
5
6
7
8
9
class Singleton {
private Singleton() {}

private final static Singleton instance = new Singleton();

public static Singleton getInstance() {
return instance;
}
}
1. 构造器私有化
 2. 类的内部创建对象
 3. 向外暴露一个静态公共方法(getInstance)
 4. 代码实现

2. 饿汉式(静态代码块)

1
2
3
4
5
6
7
8
9
10
11
12
13
class Singleton {
private Singleton() {}

private static Singleton instance;

static {
instance = new Singleton();
}

public static Singleton getInstance() {
return instance;
}
}

​ 小结:饿汉式说白了就是创建类的时候创建实例,这样可以保证线程安全,但是如果项目中没有用到就会造成资源浪费

3. 懒汉式(线程不安全)

1
2
3
4
5
6
7
8
9
10
11
12
class Singleton {
private Singleton() {}

private static Singleton instance;

public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

4. 懒汉式(线程安全,同步方法)

1
2
3
4
5
6
7
8
9
10
11
12
class Singleton {
private Singleton() {}

private static Singleton instance;

public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

这种方式会效率太低,不推荐使用

5. 懒汉式(线程安全,同步代码块)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Singleton {
private Singleton() {}

private static Singleton instance;

public static synchronized Singleton getInstance() {
if (instance == null) {
synchronized (this.class){
instance = new Singleton();
}
}
return instance;
}
}

不能起到线程同步的作用,在实际中不能使用

6.双重检查(Double Check)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Singleton {
private Singleton() {}

private volatile static Singleton instance;

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

两次 if (instance == null) 解决线程安全问题,同时解决懒加载问题,推荐使用

7.静态内部类

1
2
3
4
5
6
7
8
9
10
11
class Singleton {
private Singleton() {}

private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}

这种方式 采用了类加载机制保证初始化实例时只有一个线程

避免了线程不安全,利用静态内部类特点实现延迟加载,效率高,推荐使用

8. 枚举

不仅能避免多线程同步问题,而且还能防止反序列话重新创建新的对象提倡使用

四、小结

  • 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
  • 想实例化一个单例类的时候,使用相应的获取方法,而不是使用 new
  • 单例模式使用的场景
    1. 需要频繁进行创建和销毁的对象(各种池)
    2. 创建对象耗时过多或耗费资源过多,但是又经常用到的对象、工具类对象、频繁访问的数据库、文件的对象(数据源、session工厂等)

在实际使用中,多使用饿汉式(两种方法)、双重检查、静态内部类、枚举