创建型模式 - 单例模式 (Singleten Pattern)

创建型模式 - 单例模式 (Singleten Pattern)

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。


一共还能细分为以下几种:

  • 饿汉式单例(Eager Initialization)
  • 懒汉式单例(Lazy Initialization)
  • 双重检查锁(Double-Checked Locking)
  • 静态内部类(Static Inner Class)
  • 枚举单例(Enum Singleton)

差异对比

实现方式 线程安全 延迟加载 防止反射破坏 性能
饿汉式
懒汉式(非线程安全)
懒汉式(方法锁,线程安全) 低(加锁开销)
双重检查锁 较高
静态内部类
枚举单例

饿汉式

public class EagerSingleton {
    // 在类加载时就创建实例
    private static final EagerSingleton INSTANCE = new EagerSingleton();

    // 私有构造函数,防止外部实例化
    private EagerSingleton() {}

    // 提供全局访问点
    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

public class Main {
    public static void main(String[] args) {
        EagerSingleton singleton1 = EagerSingleton.getInstance();
        EagerSingleton singleton2 = EagerSingleton.getInstance();
        System.out.println(singleton1 == singleton2); // 输出: true
    }
}

懒汉式 - 1(非线程安全)

public class LazySingleton {
    private static LazySingleton INSTANCE;

    private LazySingleton() {}

    public static LazySingleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new LazySingleton();
        }
        return INSTANCE;
    }
}

懒汉式 - 2(线程安全,同步方法)

public class LazySafeSingleton {
    private static LazySafeSingleton INSTANCE;

    private LazySafeSingleton() {}

    // 使用 synchronized 关键字保证线程安全
    public static synchronized LazySafeSingleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new LazySafeSingleton();
        }
        return INSTANCE;
    }
}

懒汉式 - 3 (双重检查锁)

public class DoubleCheckedSingleton {
    // 使用 volatile 关键字保证可见性
    private static volatile DoubleCheckedSingleton INSTANCE;

    private DoubleCheckedSingleton() {}

    public static DoubleCheckedSingleton getInstance() {
        if (INSTANCE == null) {
            synchronized (DoubleCheckedSingleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new DoubleCheckedSingleton();
                }
            }
        }
        return INSTANCE;
    }
}

枚举形式(Enum Singleton)

枚举单例是《Effective Java》书中推荐的方式,它天然支持线程安全和防止反射攻击.(属于饿汉式范畴

public enum EnumSingleton {
    INSTANCE;

    // 添加其他方法
    public void doSomething() {
        System.out.println("Singleton is working!");
    }
}

// 使用方式
public class EnumSingletonDemo {
    public static void main(String[] args) {
        EnumSingleton singleton = EnumSingleton.INSTANCE;
        singleton.doSomething();
    }
}

静态内部类(Static Inner Class)

线程安全.(属于懒汉范畴

public class StaticInnerClassSingleton {
    private StaticInnerClassSingleton() {}

    // 静态内部类,在类加载时不会被加载,只有在第一次调用 getInstance 方法时才会加载
    private static class SingletonHolder {
        private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
    }

    public static StaticInnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

拓展: 防止被反射和序列化破坏单例性质的方法

  • 防序列化

首先你可以不实现 Serializable 就不会被序列化,也就没有这个风险.

注意除了 Java 内置的序列化机制,还存在许多第三方序列化框架,如 JSON 序列化(Jackson、Gson)、Protobuf 等。这些框架不依赖于 Serializable 接口,即使类没有实现该接口,也可以将对象序列化为 JSON 字符串、Protobuf 字节流等。所以以下方法不适用,不适用,不适用!!!

import java.io.Serializable;

// 实现 Serializable 接口
public class SerializableSingleton implements Serializable {
    // 私有静态实例
    private static final SerializableSingleton INSTANCE = new SerializableSingleton();

    // 私有构造函数
    private SerializableSingleton() {}

    // 公共静态访问方法
    public static SerializableSingleton getInstance() {
        return INSTANCE;
    }

    // 防止反序列化破坏单例  这一句是核心
    private Object readResolve() {
        return INSTANCE;
    }
}
  • 防反射
public class ReflectionSafeSingleton {
    // 使用枚举实现单例
    private static final ReflectionSafeSingleton INSTANCE = new ReflectionSafeSingleton();
    // 用于标记单例是否已经创建
    private static boolean isInstanceCreated = false;

    // 私有构造函数
    private ReflectionSafeSingleton() {
        // 防止反射破坏单例
        synchronized (ReflectionSafeSingleton.class) { // 这一句是核心,加锁并紧随其后根据 isInstanceCreated 标识来抛出异常
            if (isInstanceCreated) {
                throw new IllegalStateException("单例对象已经存在,不能通过反射创建新对象!");
            }
            isInstanceCreated = true;
        }
    }

    // 公共静态访问方法
    public static ReflectionSafeSingleton getInstance() {
        return INSTANCE;
    }
}

你可能感兴趣的:(Java设计模式,单例模式,java,设计模式)