单例模式(Singleton Pattern)

一、概念

 单例模式的核心是保证一个单例对象的全局唯一性,并且提供给外部一个访问该唯一对象的接口。

  • 解决问题:避免一个全局使用的类频繁地创建与销毁

  • 如何解决:判断是否已经有这个单例,如果有则返回,如果没有则创建。

二、参与者

Singleton 单例类,负责创建自己的唯一实例,并提供外部访问接口。

Client 用户

三、代码例子

单例类(Singleton )——懒汉式

单例类(Singleton )——饿汉式

四、UML图

五、单例的实现方式

(零)不同实现方式总结

实现方式 优缺点
饿汉式 线程安全,调用效率高 ,但是不能延迟加载
懒汉式 线程安全,调用效率不高,能延迟加载
双检锁/双重校验锁式(DCL,即 double-checked locking) 由于JVM底层内部模型原因,偶尔会出问题。不建议使用
登记式/静态内部类式 线程安全,资源利用率高,可以延时加载
枚举单例式 线程安全,调用效率高,但是不能延迟加载

(一)饿汉式

就是类加载的时候立即实例化对象,实现的步骤是先私有化构造方法,对外提供唯一的静态入口方法
饿汉式通过classloader 机制保证在类加载(static变量会在类装载时初始化)的时候就立即初始化对象,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题。因此,可以省略synchronized关键字

1.优点

没有加锁,执行效率高,性能比懒汉式更好

2.缺点

类加载的时候就初始化,不管用与不用都会占用空间,浪费内存

(二)懒汉式

外部调用 getInstance()的时候才会实例化对象。从而实现了延迟加载,但因为在方法上添加了synchronized关键字上锁,每次调用getInstance方法都会同步,所以对性能的影响比较大

(三)双重校验锁式

(四)静态内部类式

(五)枚举单例式

(六)饿汉式和懒汉式区别

饿汉就是类一旦加载,就把单例初始化完成,保证Instance的时候,单例是已经存在的了,而懒汉只有当调用Instance的时候,才回去初始化这个单例。
另外从以下两点再区分以下这两种方式:

1、线程安全:

饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题。   懒汉式本身是非线程安全的,为了实现线程安全有几种写法,本文中只提到了比较基础的一种方法。

2、资源加载和性能:

饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。

而懒汉式会延迟加载,在首次使用该类时才实例化对象,在第一次调用时要做初始化,性能上会有些延迟。

六、优缺点

(一)优点

  1. 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
  2. 避免对资源的多重占用(比如写文件操作)。
  3. 对唯一实例的访问控制,因为单例对象是全局唯一的,所以可以严格控制对象怎么访问及何时访问它;

(二)缺点

  • 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
posted @ 2022-12-03 18:25  ImreW  阅读(5)  评论(0编辑  收藏  举报