设计模式GOF23--单例模式

名词解析:GOF-->Group Of Four 四人帮

设计模式共分为以下几种模式:

  • 创建型模式:
    • 单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式
  • 结构型模式:
    • 适配器模式、桥接模式、装饰者模式、组合模式、外观模式、享元模式、代理模式
  • 行为模式:
    • 模板方法模式 、命令模式、装饰模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式。状态模式、策略模式、职责链模式、访问者模式

核心作用

保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

常见的应用场景

  • windows的任务管理器、回收站
  • 项目中的读取配置文件的类,数据库连接池,一般也只有一个对象。
  • 应用程序中的日志应用、网站中的计数器
  • Applicathion和每个Servlet也是单例
  • Spring中,每个Bean也是单例的
  • Spring MVC框架/Struts框架中,控制对象也是单例

单例模式的优点

  • 减少性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖方式时,则可以通过在应用中启动时直接产生一个单例对象,然后永久驻留在内存的方式来解决。
  • 单例模式可以在系统中设置全局的访问点,优化共享资源访问

常见的5种单例模式实现方式:

  • 主要:
    • 饿汉模式(线程安全,调用率高。不能延时加载)
    • 懒汉模式(线程安全,调用率低。可以延时加载)
  • 其他:
    • 双重检索锁式(由于JVM底层内部模型原因,偶尔会出现问题。不建议使用)
    • 静态内部类式(线程安全、调用率高、可以延时加载)
    • 枚举单例(线程安全、调用率高、不能延时加载)

饿汉模式(立即加载)

1
2
3
4
5
6
7
8
9
10
11

public class SingletonDemo1{
//1.实现私有的构造器,别人不可调用
private SingletonDemo1(){}
//2.实现一个私有的对象。 类初始化时,立即加载这个对象!由于加载类时,天然的是线程安全的
private static SingletonDemo1 instance = new SingletonDemo1();
//3.提供一个开放方法。 方法没有同步,调用效率高
public static SingletonDemo1 getInstance(){
return instance;
}
}

问题:如果只是加载本类,但是没有调用getInstance方法, 则会造成资源浪费

懒汉模式(延迟加载/懒加载)

1
2
3
4
5
6
7
8
9
10
11
12
13
14

public class SingletonDemo2{
//1.实现私有的构造器,别人不可调用
private SingletonDemo2(){}
//2.实现一个私有的对象。 类初始化时,不初始化这个对象!真正用的时候创建
private static SingletonDemo2 instance;
//3.提供一个开放方法。 方法同步,调用效率低
public static synchronized SingletonDemo1 getInstance(){
if(instance == null){
instance = new SingletonDemo2();
}
return instance;
}
}

问题:资源利用率高了,但是每次调用getInstance方法都需要同步,并发效率较低。

双重检索锁式

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
26
27
class SingletonDemo3 {

private static SingletonDemo3 instance = null;

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

private SingletonDemo3() {

}

}

静态内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 静态内部类式
* 线程安全、调用率高、可以延时加载
*/
class SingLetonStatic{
//定义静态内部类
private static class SingletonClassInstance{
private static final SingLetonStatic singLetonStatic = new SingLetonStatic();
}

private SingLetonStatic(){

}

public static SingLetonStatic getInstance(){
return SingletonClassInstance.singLetonStatic;
}
}

枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 枚举
* 线程安全、调用率高、不能延时加载
*/
enum SingLetonEnum{

//这个枚举元素,本身就是单例对象
INSTANCE;

public void SingLetonEnumOp(){

}
}
注:该博文为学习总结,视频来源为高淇java300集