定义
单例模式(Singleton Pattern)是一种创建型设计模式,它保证一个类只有一个实例,并提供一个公开节点以实现对唯一实例的访问。
使用场景
该模式主要解决一个全局类频繁使用导致的创建与销毁,应用该模式可以有效的控制实例数目,节省系统资源开销。
优点
- 在内存里只存在一个实例,减小了内存的开销(尤其是在需要频繁创建与销毁的场景下)
- 避免对资源的多重占用(例如执行IO操作时相关系统资源的占用)
缺点
没有接口,不能继承。与单一职责原则冲突:一个类应该只关心内部逻辑,而不关心外部如何进行实例化。
实现
懒汉式
懒加载:是
1 2 3 4 5 6 7 8 9 10
| public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
|
优点: 第一次调用才进行初始化,避免内存浪费
缺点:必须加锁(synchronized)才能保证单例,但加锁会影响执行效率。
饿汉式
懒加载:否
1 2 3 4 5 6 7
| public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } }
|
优点:没有加锁,执行效率相对较高。
缺点:类加载时就初始化,可能造成一定的内存浪费
双重校验锁(DCL)
懒加载:是
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Singleton { private volatile static Singleton singleton; private Singleton() {} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
|
该实现采用双锁机制,在确保多线程安全的情况下也能提供高性能,但实现逻辑相较其他方法略显复杂。
登记式/静态内部类
懒加载:是
1 2 3 4 5 6 7 8 9 10
| public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); }
private Singleton() {} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
|
优点:这种实现方式能达到双重校验锁一样的功效,但实现更为简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。
缺点:这种方式只适用于静态域的情况,双重校验锁的方式可以在实例域需要延迟初始化时使用。