单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
例如:代表JVM运行环境的Runtime类
要点
- 某个类只能有一个实例 :构造器私有化
- 它必须自行创建这个实例:含有一个该类的静态变量来保存这个唯一的实例
- 他必须自行向整个系统提供这个实例:对外提供获取该实例对象的方式,可以直接暴露或者用静态变量的get方法获取
常见形式
1.饿汉式:直接创建对象,不存在线程安全问题
- 直接实例化饿汉式(简洁直观)
public class Singleton1{ public static final Singleton1 INSTANCE = new Singleton1(); private Singleton1(){ } }
- 枚举式(最简洁)
//枚举类型:表示该类型的对象是有限的几个,我们可以限定为一个,就成了单例 public enum Singleton2{ INSTANCE }
- 静态代码块饿汉式(适合复杂实例化)
public class Singleton3{ public static final Singleton3 INSTANCE; static{ INSTANCE = new Singleton3(); } private Singleton3(){ } }
2.懒汉式:延迟创建对象
- 线程不安全(适用于单线程)
/* * (1)构造器私有化 * (2)用一个静态变量保存这个唯一的实例 * (3)提供一个静态方法,获取这个实例对象 */ public class Singleton4{ private static Singleton4 instance; private Singleton4(){ } public static Singleton4 getInstance(){ if(instance == null){ instance = new Singleton4(); } return instance; } }
- 线程安全(适用于多线程)
public class Singleton5{ private static Singleton5 instance; private Singleton5(){ } public static Singleton5 getInstance(){ synchronized(Singleton5.class){ if(instance == null){ try{ Thread.sleep(100); }catch(InterruptedException e){ e.printStackTrace(); } instance = new Singleton5(); } } return instance; } }
- 静态内部类形式(适用于多线程)
/* * 在内部类被加载和初始化,才创建INSTANCE实例对象 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独加载和初始化的 * 因为是在内部类加载和初始化时创建的,因此是线程安全的 */ public class Singleton6{ private Singleton6(){ } private static class Inner{ private static final Singleton6 INSTANCE; } public static Singleton6 getInstance(){ return Inner.INSTANCE; } }