单例模式(Singleton Pattern)
属创建类设计模式,「确保某个类只有一个实例,而且自行实例化并向整个系统提供实例」
这个模式可以说是最最常用的,什么管理类啊,资源开销比较大的类啊都可以用这个模式来做,不过工具类倒是不建议,作为工具我觉得即用即完就好,为什么要通过某个实例来维护,就用静态方法就好了。
这个模式用 uml 图已经没什么好表达的了,重点在于具体实现,这也是面试常问的点。下面就列一下具体写法,
- 饿汉式
private final static Singleton s = new Singleton();//因为很饿嘛,所以早早的创建
private Singleton(){}//这也是单例的关键,不对外提供构造方法的方式来创建实例
public static Singleton getInstance() {
return s;
}
这个方式我认为是单例最基础的,其他方式可以在这个基础之上做调整而产生。
- 懒汉式
private static Singleton s;//因为懒,所以不会在这里创建了,自然也不能用 final 修饰了
private Singleton(){}//这个还是不变的
//因为延后了创建,所以在考虑多线程的情况下要保证同步,所以用了 synchronized 修饰
public synchronized static Singleton getInstace() {
if(s == null){
s = new Singleton();
}
return;
}
- 双重检查锁机制(Double Check Lock)
private volalite static Singleton s;//这个其实和懒汉式一样,volalite 是后面为了修复问题才加上的写法。
private Singleton(){}//这个还是不变的
//这里为了避免懒汉式每次调用都做同步操作,而将同步操作往后移了,这就是双重检查的来源,其实出发点还是考虑多线程的情况。
public static Singleton getInstance() {
if(s == null) {
synchronized(Singleton.class) {
if(s == null) {
s = new Singleton();
}
}
}
return s;
}
- 静态内部类
private Singleton(){}//这个还是不变的
public static Singleton getInstance() {
return SingletonHolder.s;
}
//这种方式最大的变化在这里,唯一的实例用静态内部类包了一层
//相比饿汉式还是很像的
//这种方式也是最值得推荐的写法
private static class SingletonHolder {
private final static Singleton s = new Singleton();
}
- 枚举
public enum Singleton{
INSTANCE;
}
//这种我不熟,只做记录。但光看写法上就比前面的都简单
//那么问题来了,这么简洁的写法,为什么大家不推荐呢?我估计是 enum 自身的局限性吧,毕竟平常项目里枚举用的也不多。
以上就是几种比较常见的写法,我觉得这个模式的实现大于设计,只要抓住两个重点基本就能写出来了,1.构造方法不对外,2.通过静态方法获取唯一实例。再就是记住最基础的饿汉式,其他方式就能推导出来。
优缺点
- 只维护一个实例,减少内存开销
- 在资源开销比较大的情况下,可以提高性能
- 设置全局访问,达到数据共享
- 缺点是不适合扩展,谈不上解耦,与单一职责原则冲突
适用场景
- 很多管理类型的类,例如需要维护一些公共资源
- 对于一些类,创建对象开销比较大,可以尽量只创建一次
参考内容
「设计模式之禅(第 2 版)」
「Android 源码设计模式解析与实战」
网友评论