单例模式-有些对象也要计划生育
单例模式
保证一个类仅而有一个实例,并提供一个访问它的全局访问点。该模式保证产生唯一的实例,这样可以严格地控制客户怎么访问它以及何时访问它。
单例一般结构
/**
*
* 饿汉式创建
*
* 创建方式比较简单,
* 类加载时立即实例化对象,可能实例化的对象不被使用,造成内存的浪费
*/
public class Singleton1 {
private static Singleton1 instance = new Singleton1();
/**
* 让构造函数为 private,不让其他类可以实例化
*/
private Singleton1() {
}
public static Singleton1 getInstance() {
return instance;
}
}
/**
*
* 懒汉(饱汉)创建方式
*/
public class Singleton2 {
/**
* volatile保存内存可见性
*/
private static volatile Singleton2 singleton = null;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (singleton == null) {
//加锁
synchronized (Singleton2.class) {
// 再次判空,不然会有并发问题
if (singleton == null) {
singleton = new Singleton2();
}
}
}
return singleton;
}
}
/**
*
* 嵌套类(静态的,非静态的一般称为内部类)创建方式
*
* 只能能访问外部类的静态方法和静态属性
*
*/
public class Singleton4 {
private Singleton4() {
}
private static class SingletonHolder {
private static Singleton4 singleton = new Singleton4();
}
public static Singleton4 getInstance(){
return SingletonHolder.singleton;
}
}
/**
*
* 枚举创建方式
* 它在类加载的时候会初始化里面的所有的实例,
* 而且 JVM 保证了它们不会再被实例化,所以它天生就是单例的。
*
*/
public enum Singleton5 {
/**
* 唯一枚举,
*/
INSTANCE;
public void doSomething() {
}
}
像静态初始化这种方式,在自己被加载时就将自己实例化的称为饿汉式单例;而要在第一次被引用时才会将自己实例化的方式称为懒汉式单例。饿汉式它是类一加载就实例化的对象,所以它要提前占有系统资源,而懒汉式面临着多线程访问问题,需要加锁来保证安全性。具体使用哪一种方式,看具体需要。
嵌套类创建方式作为最经典方式,提倡使用。只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance,这样实现了延迟加载,同时又是线程安全,而且不用加锁。