单例模式多种写法代码实现

在设计模式中,单例模式(Singleton Pattern)确保一个类只有一个实例,并提供全局访问点。它有多种实现方式,通常的8种单例模式实现方式如下:

1. 饿汉式(Eager Initialization)

这种方式在类加载时就初始化了实例,保证了线程安全,但如果实例创建时资源消耗较大,而在某些情况下并不需要实例时,会造成性能浪费。

代码示例:

public class Singleton {
    private static final Singleton instance = new Singleton();
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        return instance;
    }
}

2. 懒汉式(Lazy Initialization)

懒汉式在第一次调用时创建实例,懒加载的方式减少了不必要的资源消耗,但是在多线程环境下需要额外的同步机制来确保线程安全。

代码示例:

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

3. 双重检查锁(Double-Checked Locking)

这种方式结合了懒汉式和同步机制的优点,减少了锁的开销。首先检查实例是否存在,如果没有,再加锁,保证线程安全。

代码示例:

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

4. 静态内部类(Bill Pugh Singleton)

这种方式利用了 Java 类加载机制的特性,保证线程安全,延迟初始化,并且代码更加简洁。

代码示例:

public class Singleton {
    private Singleton() {}
    
    private static class SingletonHelper {
        private static final Singleton instance = new Singleton();
    }
    
    public static Singleton getInstance() {
        return SingletonHelper.instance;
    }
}

5. 枚举式(Enum Singleton)

这种方式利用了枚举类的特性,保证了单例的线程安全、序列化安全,同时避免了反射攻击。

代码示例:

public enum Singleton {
    INSTANCE;
    
    public void doSomething() {
        System.out.println("Singleton using enum.");
    }
}

6. 登记式/容器式(Registry-Based Singleton)

这种方式通过一个容器来管理单例对象,在多线程环境下,可以保证每个对象只有一个实例。

代码示例:

import java.util.HashMap;
import java.util.Map;

public class Singleton {
    private static Map<String, Singleton> instances = new HashMap<>();
    
    private Singleton() {}
    
    public static Singleton getInstance(String key) {
        if (!instances.containsKey(key)) {
            instances.put(key, new Singleton());
        }
        return instances.get(key);
    }
}

7. Thread Local Singleton

该方式适用于每个线程都需要独立实例的情况,每个线程都拥有自己的单例对象。

代码示例:

public class Singleton {
    private static ThreadLocal<Singleton> threadLocalInstance = new ThreadLocal<Singleton>() {
        @Override
        protected Singleton initialValue() {
            return new Singleton();
        }
    };
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        return threadLocalInstance.get();
    }
}

8. 使用 volatile 关键字的延迟加载方式

该方法是双重检查锁的一种改进,确保了类的实例化不被重排序,并且提高了性能。

代码示例:

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

总结

每种单例模式都有其适用的场景和优缺点,选择哪种模式取决于具体的需求。例如,枚举式单例(Enum Singleton)是最推荐的方式,因为它既简洁又安全,能防止反射攻击,并且在 JVM 中由类加载机制确保线程安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昔我往昔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值