必知必会的设计模式6

单例模式(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 源码设计模式解析与实战」

你可能感兴趣的:(必知必会的设计模式6)