❝学习设计模式不要死板, 有时候各个设计模式之间没有明显的界限
❞
今天说说我在看框架源码过程中遇到的关于单例模式的设计。
系列问题
1.单例模式
确保全局只有一个实例。减少该类实例的频繁创建,节省资源。
使用场景:
- 要求生产唯一序列号。
- WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
- 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
常见使用方式:
- 懒汉式,线程不安全版本。 不催不创建实例。
public class Singleton { private static Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
- 懒汉式,线程安全版本。实例创建方法加锁(粗粒度锁)
- 懒汉式,双重校验锁版本(安全)。实例创建方法双重校验(锁细化)
- 懒汉式,静态内部类(安全)。调用创建方法时,触发类的加载,利用类只会被加载一次这个特性,保证单例。
public class Singleton { private Singleton() {} private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonInstance.INSTANCE; } }
- 饿汉式,静态常量/静态代码块(不如翻译为勤快式),利用类加载时的初始化。static:类变量,总能拿到一个初始化值。final:禁止指令重排;保证必然初始化。
public class Singleton { private final static Singleton INSTANCE = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return INSTANCE; } /* private static Singleton instance; static { instance = new Singleton(); } */ }
- 枚举:线程安全。 但是可读性很差。
2.spring 中单例模式
Spring 下默认的 bean 均为 singleton,bean 统一交给容器管理,获取对象从容器里取。
但也有一些不在容器的管理范围的组件。spring 使用了单例模式.
2.1 OrderComparator 比较器
spring 中很多组件都是有顺序的,你也许对@Order 注解很有印象,定义组件的顺序。 OrderComparator 就是那个比较器
来看看源码
public class OrderComparator implements Comparator<Object> { public static final OrderComparator INSTANCE = new OrderComparator(); ... }
还有他的子类AnnotationAwareOrderComparator
public class AnnotationAwareOrderComparator extends OrderComparator { public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator(); }
都是典型的饿汉式。
本文使用 mdnice 排版