设计模式之-单例模式

什么是单例模式?

单例模式确保一个类只有一个实例,并提供一个全局访问点。就像公司里的CEO,整个公司只有一个,任何需要CEO的地方都访问同一个对象。

简单来说,单例模式:

  • 控制实例数量(只允许创建一个)
  • 提供全局访问点
  • 通常自行管理自己的实例

主要解决什么问题?

单例模式主要解决以下问题:

  1. 资源共用问题:如数据库连接池、线程池、缓存等只需要一个实例
  2. 全局状态管理:配置信息、计数器等需要全局唯一的状态
  3. 避免重复创建:某些对象创建成本高,需要复用

何时使用单例模式?

当你遇到以下场景时,考虑使用单例模式:

  • 当类只能有一个实例且客户端需要从众所周知的访问点访问它时
  • 当唯一实例应该通过子类化可扩展,且客户端无需修改代码就能使用扩展后的实例时
  • 需要严格控制全局变量时(比全局变量更优雅)

单例模式的优点

  1. 控制实例数量:确保只有一个实例存在
  2. 全局访问:提供统一的访问点
  3. 延迟初始化:可以在需要时才创建实例
  4. 减少资源消耗:避免重复创建消耗资源的对象

单例模式的缺点

  1. 违反单一职责原则:既管理自己的创建又负责业务逻辑
  2. 难以测试:全局状态使得单元测试困难
  3. 隐藏依赖:单例的调用关系不明显
  4. 多线程问题:需要特殊处理以保证线程安全
  5. 可能成为"上帝对象":过度使用会导致设计问题

代码示例:多种实现方式

1. 饿汉式(线程安全)

public class EagerSingleton {
    // 类加载时就初始化
    private static final EagerSingleton instance = new EagerSingleton();
    
    // 私有构造函数
    private EagerSingleton() {}
    
    // 全局访问点
    public static EagerSingleton getInstance() {
        return instance;
    }
    
    // 示例方法
    public void showMessage() {
        System.out.println("Hello, I'm an Eager Singleton!");
    }
}

2. 懒汉式(线程不安全)

public class LazySingleton {
    private static LazySingleton instance;
    
    private LazySingleton() {}
    
    // 非线程安全
    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
    
    public void showMessage() {
        System.out.println("Hello, I'm a Lazy Singleton!");
    }
}

3. 双重检查锁(线程安全)

public class ThreadSafeSingleton {
    // volatile保证可见性和禁止指令重排序
    private static volatile ThreadSafeSingleton instance;
    
    private ThreadSafeSingleton() {}
    
    public static ThreadSafeSingleton getInstance() {
        // 第一次检查
        if (instance == null) {
            synchronized (ThreadSafeSingleton.class) {
                // 第二次检查
                if (instance == null) {
                    instance = new ThreadSafeSingleton();
                }
            }
        }
        return instance;
    }
    
    public void showMessage() {
        System.out.println("Hello, I'm a Thread-Safe Singleton!");
    }
}

4. 静态内部类实现(推荐)

public class InnerClassSingleton {
    private InnerClassSingleton() {}
    
    // 静态内部类在第一次使用时加载
    private static class SingletonHolder {
        private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }
    
    public static InnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
    
    public void showMessage() {
        System.out.println("Hello, I'm an Inner Class Singleton!");
    }
}

5. 枚举实现(最佳实践,防反射攻击)

public enum EnumSingleton {
    INSTANCE;
    
    public void showMessage() {
        System.out.println("Hello, I'm an Enum Singleton!");
    }
}

客户端使用示例

public class SingletonDemo {
    public static void main(String[] args) {
        // 饿汉式
        EagerSingleton eager1 = EagerSingleton.getInstance();
        EagerSingleton eager2 = EagerSingleton.getInstance();
        System.out.println("EagerSingleton same instance? " + (eager1 == eager2));
        eager1.showMessage();
        
        // 枚举式
        EnumSingleton enum1 = EnumSingleton.INSTANCE;
        EnumSingleton enum2 = EnumSingleton.INSTANCE;
        System.out.println("EnumSingleton same instance? " + (enum1 == enum2));
        enum1.showMessage();
    }
}

实际应用场景

单例模式在Java中有许多实际应用:

  1. 日志记录器:整个应用共享一个日志实例
  2. 配置管理:全局配置信息
  3. 数据库连接池:管理数据库连接资源
  4. 设备管理器:如打印机管理器
  5. Spring中的Bean:默认scope就是单例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值