设计模式之单例模式

单例模式(Singleton Pattern) 是设计模式中的一种,它确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。在很多场景中,我们都需要这样的功能,比如配置文件的读取、线程池的管理、数据库的连接等。下面将详细解释单例模式的各个方面。

1. 单例模式的特点

  1. 全局唯一:一个类只有一个实例。
  2. 预先创建:这个实例在类加载时就已经被创建,或者在第一次使用时被创建。
  3. 简单访问:通过类名直接访问这个实例,无需实例化。

2. 单例模式的实现方式

2.1 饿汉式(静态常量)

在类加载时就完成了实例化,避免了线程同步问题。

public class Singleton {  
    private static final Singleton INSTANCE = new Singleton();  
  
    private Singleton() {}  
  
    public static Singleton getInstance() {  
        return INSTANCE;  
    }  
}
2.2 懒汉式(线程不安全)

在第一次调用 getInstance() 时才实例化,但存在线程安全问题。

public class Singleton {  
    private static Singleton instance;  
  
    private Singleton() {}  
  
    public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}
2.3 懒汉式(线程安全,同步方法)

使用 synchronized 关键字对 getInstance() 方法进行同步,但效率较低。

public class Singleton {  
    private static Singleton instance;  
  
    private Singleton() {}  
  
    public static synchronized Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}
2.4 懒汉式(双重检查锁定/DCL,推荐)

通过双重检查锁定来实现线程安全和延迟加载。

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

注意:在 Java 5.0 及以上版本中,需要加上 volatile 关键字来确保多线程环境下实例的可见性。

2.5 静态内部类

利用了 classloader 的机制来保证初始化 instance 时只有一个线程。

public class Singleton {  
    private Singleton() {}  
  
    private static class SingletonHolder {  
        private static final Singleton INSTANCE = new Singleton();  
    }  
  
    public static Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  
}
2.6 枚举

在 Java 枚举中,所有的枚举值都是自动被线程安全的。

public enum Singleton {  
    INSTANCE;  
  
    public void doSomething() {  
        // ...  
    }  
}

3. 注意事项

  • 线程安全:在多线程环境下,要确保单例模式的线程安全。
  • 延迟加载:在某些场景下,我们可能希望单例对象在第一次使用时才被创建,这就需要使用懒汉式或静态内部类的方式。
  • 序列化:如果单例对象需要被序列化,那么在反序列化时可能会创建新的实例。为了解决这个问题,可以在单例类中实现 readResolve() 方法。
  • 单例的持有:通常我们会将单例对象的引用保存在一个静态变量中,但也可以考虑使用其他方式,比如使用容器来管理单例对象。
  • 避免在单例类中持有状态:单例对象通常是无状态的,如果确实需要持有状态,那么应该谨慎处理并发访问和状态同步的问题。

总结
单例模式是一种非常重要的设计模式,通过确保一个类只有一个实例,可以有效控制资源的使用,提高系统的性能和稳定性。然而,也需要注意不要过度使用单例模式,以免导致代码结构过于复杂和难以维护。

后续会持续更新分享相关内容,记得关注哦!

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值