程序员设计模式之JAVA

Singleton

2020-09-24  本文已影响0人  93张先生

单例模式

单例模式允许一个应用程序在每一个 JVM 实例中有且只有一个类的实例对象。

特征

饿汉模式

public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();
 
    // private constructor
    private EagerSingleton() {
    }
 
    public static EagerSingleton getInstance() {
        return instance;
    }
}

懒汉模式

public class LazySingleton {
    private static volatile LazySingleton instance = null;
 
    // private constructor
    private LazySingleton() {
    }
 
    public static LazySingleton getInstance() {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                // Double check
                if (instance == null) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}
双重懒加载

使用volatile关键字的目的不是保证可见性(synchronized已经保证了可见性),而是为了保证顺序性。具体来说,INSTANCE = new Singleton()不是原子操作,实际上被拆分为了三步:1) 分配内存;2) 初始化对象;3) 将INSTANCE指向分配的对象内存地址。 如果没有volatile,可能会发生指令重排,使得INSTANCE先指向内存地址,而对象尚未初始化,其它线程直接使用INSTANCE引用进行对象操作时出错。

双重空检查:防止两个线程,实例化两个对象。一个线程T1 读到对象为空,另一个线程T2读到对象也为空,T1 加锁实例化,T2 加锁实例化。这样就是两个实例了。

静态代码块

public class StaticBlockSingleton {
    private static final StaticBlockSingleton INSTANCE;
 
    static {
        try {
            INSTANCE = new StaticBlockSingleton();
        } catch (Exception e) {
            throw new RuntimeException("Uffff, i was not expecting this!", e);
        }
    }
 
    public static StaticBlockSingleton getInstance() {
        return INSTANCE;
    }
 
    private StaticBlockSingleton() {
        // ...
    }
}

静态内部类

推荐

public class BillPughSingleton {
    private BillPughSingleton() {
    }
 
    private static class LazyHolder {
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }
 
    public static BillPughSingleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

枚举

public enum EnumSingleton {
    INSTANCE;
    public void someMethod(String param) {
        // some class member
    }

  // 该方法非必须,只是为了保证与其它方案一样使用静态方法得到实例
  public static EnumSingleton getInstance() {
    return INSTANCE;
  }
}

序列化&反序列化问题

public class DemoSingleton implements Serializable {
    private static final long serialVersionUID = 1L;
 
    private DemoSingleton() {
        // private constructor
    }
 
    private static class DemoSingletonHolder {
        public static final DemoSingleton INSTANCE = new DemoSingleton();
    }
 
    public static DemoSingleton getInstance() {
        return DemoSingletonHolder.INSTANCE;
    }
 
    protected Object readResolve() {
        return getInstance();
    }
}

场景

public class Runtime {
    private static Runtime currentRuntime = new Runtime();
    public static Runtime getRuntime() {
        return currentRuntime;
    }
}
public abstract class VFS {
   private static class VFSHolder {
    // 单例模式, 全局唯一 VFS 对象
    static final VFS INSTANCE = createVFS();

    static VFS createVFS() {
      // Try the user implementations first, then the built-ins
      // 优先使用用户自义的 VFS 现, 如采没自定义 VFS 实现,则使用 MyBatis 提供的 VFS 实现
      List<Class<? extends VFS>> impls = new ArrayList<>();
      impls.addAll(USER_IMPLEMENTATIONS);
      impls.addAll(Arrays.asList((Class<? extends VFS>[]) IMPLEMENTATIONS));

      // Try each implementation class until a valid one is found
      // 造历 impls 集合,依次实例化 VFS 对象并检测 VFS 对象是否有效,一旦得到有效的 VFS 对象,则结束循环
      VFS vfs = null;
      for (int i = 0; vfs == null || !vfs.isValid(); i++) {
        Class<? extends VFS> impl = impls.get(i);
          // 通过类的构造方法创建VFS实例
          vfs = impl.getDeclaredConstructor().newInstance();
          if (!vfs.isValid()) {
            if (log.isDebugEnabled()) {
              log.debug("VFS implementation " + impl.getName() +
                  " is not valid in this environment.");
            }
          }
      return vfs;
    }
  }

  /**
   * Get the singleton {@link VFS} instance. If no {@link VFS} implementation can be found for the
   * current environment, then this method returns null.
   */
  public static VFS getInstance() {
    return VFSHolder.INSTANCE;
  }
}

VFS 表示虚件系统 Virtual File System 来查找指定路径下的资源。资源比如: jar 或者 class 文件

上一篇 下一篇

猜你喜欢

热点阅读