单例模式是一种创建型设计模式,它的目的是保证一个类只有一个实例,并提供一个全局的访问点来获取这个实例。
在软件开发中,有些类我们只需要一个实例就足够了,比如一个数据库连接池、线程池、日志系统或者系统配置信息。使用单例模式可以确保只有一个实例对象存在,这样可以节省内存资源和避免多个实例之间的冲突。
将类的构造函数设为私有,这样外部就无法直接创建对象。
提供一个静态方法来获取类的唯一实例,通常被称为getInstance()方法。在这个方法内部,我们可以控制对象的创建和返回。
下面是一个简单的Java示例,展示了如何实现单例模式:
public class Singleton { private static Singleton instance; private Singleton() { // 私有构造函数 } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
在这个例子中,Singleton类的构造函数被设为私有,防止外部通过 new 关键字直接创建对象。getInstance()方法检查实例是否已经存在,如果不存在,则创建一个新的实例并返回,如果存在,则直接返回现有实例。
需要注意的是,以上是一个简单的懒汉式单例模式的实现。在多线程环境下,为了确保线程安全,可以在getInstance()方法加锁或者使用双重检查锁定等机制。
当然,还有其他的单例模式实现方式,比如饿汉式单例、静态内部类单例等。每种实现方式都有其适用的场景和特点。
饿汉式单例(2种):
/** * 饿汉:在类刚一初始化的时候就立即把单例对象创建出来,下面两种都是饿汉模式的实现 */ public class Singleton { private Singleton() {} private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } private static Singleton instance1=null; static { instance1=new Singleton(); } public Singleton getInstance1(){ return instance1; } }
懒汉式单例(4种):
/** * 懒汉:懒加载,就是在需要的时候才回去创建对象 */ public class Singleton { private Singleton() { } /** * 1.单例模式【线程不安全,不推荐】 * 因为没有加锁synchronized,严格意义上不算单例。 * @return */ private static Singleton instance1; public static Singleton getInstance() { if (instance1 == null) {//这里是不安全的,可能得到两个不同的实例 instance1 = new Singleton(); } return instance1; } /** * 2.线程安全但效率低【不推荐】 * 99%的情况下不需要同步 * @return */ private static Singleton instance2; public static synchronized Singleton getInstance1() { if (instance2 == null) { instance2 = new Singleton(); } return instance2; } /** * 3.单例模式,线程不安全【不推荐】 * 虽然加了锁,但是等到第一个线程执行完instance2=new Singleton();跳出锁时 * 令一个线程恰好刚判断完instance2为null,此时又会加载另一个实例 */ private static Singleton instance3; public static Singleton getInstance2() { if (instance3 == null) { synchronized (Singleton.class) {//不安全 instance3 = new Singleton(); } } return instance3; } /** * 4.双重校验锁:延迟加载+线程安全【推荐】 */ private static volatile Singleton instance4; public static Singleton getInstance4() { if (instance4 == null) { synchronized (Singleton.class) { if (instance4 == null) { instance4 = new Singleton(); } } } return instance4; } }
静态内部单例:
/** * 静态内部类【推荐】 * 这种方式跟饿汉式方式采用的机制类似,但又有不同。 * 两者都是采用了类装载的机制来保证初始化实例时只有一个线程。 * 不同的地方: * 在饿汉式方式是只要Singleton类被装载就会实例化, * 内部类是在需要实例化时,调用getInstance方法,才会装载SingletonHolder类 * 优点:避免了线程不安全,延迟加载,效率高。 */ public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() { } public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
枚举类单例:
/** * 枚举实现 * 这种方式还没有被广泛采用,但是这种是实现单例的最佳方式。 * 线程安全,自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化 */ public enum Singleton { INSTANCE; public void whateverMethod(){ System.out.println("单例模式实现的最佳方式"); } }
希望这个简单的介绍能够帮助你理解单例模式的基本概念和应用。
本文固定URL:https://www.dotcpp.com/course/1359