Java创建型模式(一):单例设计模式
单例设计模式是一种常用的创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。单例模式在Java中有多种实现方式,主要包括饿汉式、懒汉式、枚举式等。接下来将对这些方法进行详细讲解和代码示例。
一、饿汉式单例
饿汉式单例在类加载时就创建好实例,由于在类加载时就创建好对象,因此它是线程安全的。代码如下:
public class SingletonEager {
private static final SingletonEager INSTANCE = new SingletonEager();
// 私有构造函数,防止外部实例化
private SingletonEager() {}
public static SingletonEager getInstance() {
return INSTANCE;
}
}
// 使用案例
public class Test {
public static void main(String[] args) {
SingletonEager instance1 = SingletonEager.getInstance();
SingletonEager instance2 = SingletonEager.getInstance();
System.out.println(instance1 == instance2); // 输出 true
}
}
二、懒汉式单例
懒汉式单例在第一次使用实例时才会创建对象。这种方式在多线程环境下可能会导致问题,需进行适当的同步处理。
public class SingletonLazy {
private static SingletonLazy instance;
// 私有构造函数,防止外部实例化
private SingletonLazy() {}
public static SingletonLazy getInstance() {
if (instance == null) {
synchronized (SingletonLazy.class) {
if (instance == null) { // 双重检查锁定
instance = new SingletonLazy();
}
}
}
return instance;
}
}
// 使用案例
public class Test {
public static void main(String[] args) {
SingletonLazy instance1 = SingletonLazy.getInstance();
SingletonLazy instance2 = SingletonLazy.getInstance();
System.out.println(instance1 == instance2); // 输出 true
}
}
三、枚举式单例
在Java中,使用枚举实现单例模式是最简单的方式。这种方法天生支持序列化,并且通过JVM来保证单例性。
public enum SingletonEnum {
INSTANCE;
public void doSomething() {
// 方法实现
}
}
// 使用案例
public class Test {
public static void main(String[] args) {
SingletonEnum instance1 = SingletonEnum.INSTANCE;
SingletonEnum instance2 = SingletonEnum.INSTANCE;
System.out.println(instance1 == instance2); // 输出 true
}
}
四、破坏单例模式的方式
- 序列化与反序列化:在反序列化时会重新创建实例,可以通过实现
readResolve
方法来避免这种情况。
private Object readResolve() {
return INSTANCE;
}
- 反射:使用反射可以访问私有构造函数,因此需要在构造函数中进行检查,防止通过反射创建多个实例。
private SingletonLazy() {
if (instance != null) {
throw new IllegalStateException("Only one instance is allowed!");
}
}
总结
单例设计模式提供了一种控制实例数量的解决方案,适合使用在需要全局访问的场景中。饿汉式、懒汉式和枚举式各有优缺点,开发者可以根据实际需求选择合适的实现方式。同时,当我们设计单例模式时,应注意序列化和反射带来的破坏风险,采取适当的措施进行防范。