单例模式

概述

单例模式的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。属于设计模式三大类中的创建型模式
单例模式具有典型的三个特点

  • 只有一个实例。
  • 自我实例化。
  • 提供全局访问点。

UML结构图非常简单,就只有一个类,如下图:

优缺点

  • 优点:由于单例模式只生成一个实例,所以能够节省系统资源,减少性能开销,提高系统效率,同时也能够严格的控制客户对他的访问。
  • 缺点:也正是因为系统只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责”的原则,同时也没有抽象类,这样扩展起来有一定的困难。

实现方式

  • 饿汉式:线程安全,调用效率高,但是不能延迟加载。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package class;

/**
* @author zhang
* @date 2020/7/23 18:02
*/
public class SingletonDemo1 {
//线程安全,类初始化立即加载这个对象
private static SingletonDemo1 singletonDemo1 = new SingletonDemo1();

//私有构造方法-->外界不能通过new来创建对象
private SingletonDemo1(){}

//提供一个公开的静态方法来创建当前类的对象
public static SingletonDemo1 getInstance(){
return singletonDemo1;
}
}

由于该模式类加载的时候对象就已创建了,所以加载类的速度比较慢,但是获取对象的速度比较块,且是线程安全

的。

  • 懒汉式:线程不安全
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package class;

import javax.crypto.spec.PSource;

/**
* @author zhang
* @date 2020/7/23 18:09
*/
public class SingletonDemo2 {
private static SingletonDemo2 singletonDemo2;

//提供私有的构造方法
private SingletonDemo2(){}

public static SingletonDemo2 getInstance(){
if (singletonDemo2 == null){
singletonDemo2 = new SingletonDemo2();
}
return singletonDemo2;
}
}

由于该模式是在运行时加载对象的,所以加载类比较快,但是对象的获取速度相对较慢,且线程不安全如果想要线程安全的话可以加上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
package class;

/**
* @author zhang
* @date 2020/7/23 18:19
*/
public class SingletonDemo3 {
//使用双重锁机制
private static volatile SingletonDemo3 singletonDemo3;

//提供私有的构造方法
private SingletonDemo3(){}

public static SingletonDemo3 getInstance(){
if (singletonDemo3 == null){
//线程同步加锁
synchronized (SingletonDemo3.class){
if (singletonDemo3 == null){
singletonDemo3 = new SingletonDemo3();
}
}
}
return singletonDemo3;
}
}

优点:线程安全,缺点:每次获取实例都要加锁,耗费资源,其实只要实例已经生成,以后获取就不需要再锁了

常见应用场景

  1. 网站计数器。
  2. 项目中用于读取配置文件的类。
  3. 数据库连接池。因为数据库连接池是一种数据库资源。
  4. Spring中,每个Bean默认都是单例的,这样便于Spring容器进行管理。
  5. Servlet中Application
  6. Windows中任务管理器,回收站。
    等等。

评论