概念:
单例模式在23种设计模式中属于创建型模式,是常见的设计模式之一。
案例:
这里以经典的数据库驱动连接工具类为例;
数据库连接工具类在各个业务的dao层会被初始化调用;
而每一次初始化都会在堆内存中申请一片空间,这是对堆内存资源的浪费;
如果在堆内存只开辟一片空间,各个业务的Dao层建立不同的引用进行操作,就可以资源利用最大化;
单例设计模式就应运而生,它就是为了解决对象初始化,造成资源浪费的情况;
术语
单例:Singleton
三要素
- 私有的构造方法;
- 指向自己实例的私有静态引用;
- 以自己实例为返回值的静态的公有方法。 分类
1.饿汉式(静态常量)
/**
*
* @author 借我丹青妙笔
* @create 2022-01-02 18:01 饿汉式(静态常量)
*/
public class DBAccess {
// 构造器私有化,避免外部创建对象
private DBAccess() {
}
// static修饰,保障其能够被静态方法访问
private final static DBAccess dbAccess = new DBAccess();
// 外部直接调用静态方法实例化对象
public static DBAccess getInstance() {
return dbAccess;
}
}
2.饿汉式(静态代码块)
/**
* 饿汉式(静态代码块)
*/
class DBAccess2 {
private DBAccess2() {
}
private static DBAccess2 dbAccess = null;
static {
dbAccess = new DBAccess2();
}
public static DBAccess2 getInstance() {
return dbAccess;
}
}
3.懒汉式(线程不安全)
/**
* 懒汉式(线程不安全)
*/
class DBAccess3 {
private DBAccess3() {
}
private static DBAccess3 dbAccess = null;
public static DBAccess3 getInstance() {
if (dbAccess == null) {
dbAccess = new DBAccess3();
}
return dbAccess;
}
}
4.懒汉式(线程安全,同步代码块)
/**
* 懒汉式(同步代码块)
*/
class DBAccess4 {
private DBAccess4() {
}
private static DBAccess4 dbAccess = null;
public static DBAccess4 getInstance() {
synchronized (DBAccess4.class) {
if (dbAccess == null) {
dbAccess = new DBAccess4();
}
}
return dbAccess;
}
}
5.懒汉式(线程安全,同步方法)
/**
* 懒汉式(线程安全,同步方法)
*/
class DBAccess5 {
private DBAccess5() {
}
private static DBAccess5 dbAccess = null;
public synchronized static DBAccess5 getInstance() {
if (dbAccess == null) {
dbAccess = new DBAccess5();
}
return dbAccess;
}
}
6.双重检查
/**
* 双重检查
*/
class DBAccess6 {
private DBAccess6() {
}
private static DBAccess6 dbAccess = null;
public static DBAccess6 getInstance() {
if (dbAccess == null) {
synchronized (DBAccess6.class) {
if (dbAccess == null) {
dbAccess = new DBAccess6();
}
}
}
return dbAccess;
// return new DBAccess6();
}
}
7.静态内部类
/**
* 静态内部类
*/
class DBAccess7 {
private DBAccess7() {
}
private static class DBAccess7Instance {
private static DBAccess7 dbAccess = new DBAccess7();
}
public static DBAccess7 getInstance() {
return DBAccess7Instance.dbAccess;
}
}
8.枚举
/**
* 枚举
*/
enum DBAccess8 {
DBACCESS;
public static DBAccess8 getInstance() {
return DBAccess8.DBACCESS;
}
}
饿汉式和懒汉式的区别
(1)饿汉式和懒汉式的主要区别是他们使用的加载策略不同,饿汉式使用的是立即加载,而懒汉式用的是延迟加载(懒加载)。简单来说就是饿汉式不管你用不用,它都实例了。而懒汉式是当你调用方法时它才去实例。
(2)饿汉式虽存在性能问题,但它是线程安全的,而懒汉式可能存在线程不安全的问题,当然也可以通过同步代码块或同步方法的方式解决,如上面4、5。(注:4比5的性能更好)。
结论:
单例中两种饿汉式可用,但是存在性能问题 单例中三种懒汉式不推荐,存在线程安全问题,同步方法的方式解决了线程的问题,但是性能极差 最后三种单例模式值得推荐
注意事项
系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new
应用
- jdk源码中Runtime类
- tomcat中ApplicationContext类
- session 工厂
通过以上讲解,为大家详细介绍了Java23种设计模式里比较常见的单例模式。想要系统学习更多编程基础知识的同学可以戳视频链接继续~