枚举单例案例

wen java案例 2

本文目录导读:

枚举单例案例

  1. 基础枚举单例
  2. 测试类
  3. 带数据和方法的枚举单例
  4. 处理序列化的枚举单例
  5. 带延迟初始化的枚举单例(复杂场景)
  6. 完整的应用示例
  7. 防止反射破坏的完整示例
  8. 枚举单例的核心优势
  9. 最佳实践建议

我来为你提供一个完整的枚举单例案例,并详细解释其特点。

基础枚举单例

public enum Singleton {
    INSTANCE;
    private String config;
    // 构造函数(枚举的构造器默认private)
    Singleton() {
        config = "默认配置";
        // 可以在这里进行初始化操作
        System.out.println("枚举单例被初始化");
    }
    public void doSomething() {
        System.out.println("执行方法,配置为:" + config);
    }
    public void setConfig(String config) {
        this.config = config;
    }
}

测试类

public class EnumSingletonTest {
    public static void main(String[] args) {
        // 使用单例
        Singleton singleton1 = Singleton.INSTANCE;
        Singleton singleton2 = Singleton.INSTANCE;
        System.out.println("是否为同一个实例: " + (singleton1 == singleton2));
        System.out.println("hashCode 是否相同: " + 
            (singleton1.hashCode() == singleton2.hashCode()));
        singleton1.doSomething();
        // 修改配置
        singleton1.setConfig("新的配置");
        singleton2.doSomething(); // 验证配置已更新
        // 测试多线程环境
        testMultiThread();
    }
    private static void testMultiThread() {
        Runnable task = () -> {
            Singleton singleton = Singleton.INSTANCE;
            System.out.println(Thread.currentThread().getName() + 
                " - 实例: " + singleton.hashCode());
        };
        for (int i = 0; i < 5; i++) {
            new Thread(task, "线程-" + i).start();
        }
    }
}

带数据和方法的枚举单例

import java.io.*;
public enum DatabaseConnection {
    INSTANCE;
    // 模拟数据库连接池
    private ConnectionPool pool;
    private int connectionCount;
    DatabaseConnection() {
        System.out.println("初始化数据库连接池...");
        pool = new ConnectionPool();
        connectionCount = 0;
    }
    // 模拟连接池类
    static class ConnectionPool {
        void connect() {
            System.out.println("创建数据库连接");
        }
        void disconnect() {
            System.out.println("关闭数据库连接");
        }
    }
    public synchronized void connect() {
        connectionCount++;
        pool.connect();
    }
    public synchronized void disconnect() {
        if (connectionCount > 0) {
            connectionCount--;
        }
        pool.disconnect();
    }
    public int getConnectionCount() {
        return connectionCount;
    }
    public void showStatus() {
        System.out.println("当前活跃连接数: " + connectionCount);
    }
}

处理序列化的枚举单例

import java.io.*;
public enum SerializableSingleton implements Serializable {
    INSTANCE;
    private String data;
    public String getData() {
        return data;
    }
    public void setData(String data) {
        this.data = data;
    }
    // 枚举天然防止序列化破坏单例,无需实现readResolve()
    // 但可以重写readResolve来确保反序列化后返回相同实例
    private Object readResolve() {
        return INSTANCE;
    }
    // 测试序列化行为
    public static void main(String[] args) throws Exception {
        SerializableSingleton instance = SerializableSingleton.INSTANCE;
        instance.setData("测试数据");
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(instance);
        oos.close();
        // 反序列化
        ObjectInputStream ois = new ObjectInputStream(
            new ByteArrayInputStream(bos.toByteArray()));
        SerializableSingleton deserialized = (SerializableSingleton) ois.readObject();
        ois.close();
        System.out.println("序列化前后是否相同: " + (instance == deserialized));
        System.out.println("反序列化后数据: " + deserialized.getData());
    }
}

带延迟初始化的枚举单例(复杂场景)

public enum LazySingleton {
    INSTANCE;
    // 私有静态内部类用于延迟加载复杂资源
    private enum ResourceHolder {
        INSTANCE;
        private ComplexResource resource;
        ResourceHolder() {
            System.out.println("延迟加载复杂资源...");
            resource = new ComplexResource();
        }
    }
    public static class ComplexResource {
        private String name;
        ComplexResource() {
            name = "复杂资源-" + System.currentTimeMillis();
        }
        public void process() {
            System.out.println("处理资源: " + name);
        }
    }
    public ComplexResource getResource() {
        return ResourceHolder.INSTANCE.resource;
    }
}

完整的应用示例

public class CompleteExample {
    // 配置管理单例
    public enum ConfigManager {
        INSTANCE;
        private Properties properties = new Properties();
        ConfigManager() {
            loadDefaultConfig();
        }
        private void loadDefaultConfig() {
            properties.setProperty("app.name", "我的应用");
            properties.setProperty("app.version", "1.0.0");
            properties.setProperty("database.url", "jdbc:mysql://localhost:3306/mydb");
            properties.setProperty("database.user", "root");
        }
        public String getProperty(String key) {
            return properties.getProperty(key);
        }
        public void setProperty(String key, String value) {
            properties.setProperty(key, value);
        }
        public void displayConfig() {
            System.out.println("=== 应用配置 ===");
            properties.forEach((k, v) -> 
                System.out.println(k + " = " + v));
        }
    }
    public static void main(String[] args) {
        // 使用配置管理单例
        System.out.println("应用名: " + ConfigManager.INSTANCE.getProperty("app.name"));
        System.out.println("数据库URL: " + ConfigManager.INSTANCE.getProperty("database.url"));
        // 修改配置
        ConfigManager.INSTANCE.setProperty("app.version", "2.0.0");
        System.out.println("更新后版本: " + ConfigManager.INSTANCE.getProperty("app.version"));
        // 显示所有配置
        ConfigManager.INSTANCE.displayConfig();
    }
}

防止反射破坏的完整示例

import java.lang.reflect.Constructor;
public enum SafeSingleton implements Cloneable {
    INSTANCE;
    private String name;
    // 防止克隆
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("单例不能被克隆");
    }
    // 测试反射攻击
    public static void testReflection() {
        try {
            Constructor<SafeSingleton> constructor = 
                SafeSingleton.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            SafeSingleton anotherInstance = constructor.newInstance();
            System.out.println("反射创建的实例: " + anotherInstance);
        } catch (Exception e) {
            System.out.println("反射攻击失败: " + e.getMessage());
        }
    }
    public static void main(String[] args) {
        SafeSingleton instance1 = SafeSingleton.INSTANCE;
        SafeSingleton instance2 = SafeSingleton.INSTANCE;
        System.out.println("两个实例是否相同: " + (instance1 == instance2));
        // 测试反射攻击
        testReflection();
        // 测试克隆
        try {
            instance1.clone();
        } catch (Exception e) {
            System.out.println("克隆失败: " + e.getMessage());
        }
    }
}

枚举单例的核心优势

  1. 线程安全:枚举实例的创建由JVM保证,天然线程安全
  2. 防反射攻击:枚举没有公共构造器,反射无法创建新实例
  3. 防序列化破坏:枚举反序列化时自动复用现有实例
  4. 防克隆:枚举不能使用clone()方法创建新实例
  5. 简洁直观:代码简洁,易于理解和使用

最佳实践建议

// 推荐的枚举单例模式
public enum RecommendedSingleton {
    INSTANCE;
    // 私有字段
    private DatabaseConnector db;
    private CacheManager cache;
    // 构造函数中初始化所有资源
    RecommendedSingleton() {
        // 初始化资源
        db = new DatabaseConnector();
        cache = new CacheManager();
    }
    // 提供业务方法
    public void connectDB() {
        db.connect();
    }
    public Object getFromCache(String key) {
        return cache.get(key);
    }
}

枚举单例是目前公认的最安全的单例实现方式之一,它很好地解决了传统单例模式中存在的线程安全、反射攻击、序列化破坏等问题。

抱歉,评论功能暂时关闭!