概念:是应用最广泛的设计模式之一,解决的就是在程序运行过程当中一个类最多只能创建一个对象的问题,保证一个类只有一个实例
避免对象不一致的状态
引入问题:例如一家公司只有一个打印机,但是有多个部门,A部门想使用打印机就创建A部门对象,B部门使用打印机就会创建B部门对象
通过单例模式构造唯一实例:懒汉式、饿汉式、静态内部类
步骤1:创建一个静态类成员
步骤2:构造方法私有化
步骤3:提供一个公共的创建实例方法
实现:构造函数私有化(单例类不能再其他类中实例化,只能被自身实例化)
拥有一个保存类的实例的静态成员变量
通过一个公共的静态方法返回单例类对象唯一实例
饿汉式:立即加载+线程安全
特点:提前进行实例化,立即加载,没有延迟加载,不管有没有被使用都会有一个初始化的实例加载在内存中,jvm保证类在加载过程中static代码块在多线程或者单线程都正确并只执行一次,线程安全,不会出现像懒汉模式中的多线程问题,资源浪费
public class Cz { //静态全局变量,内存唯一,创建一个对象出来 private static Cz cz = new Cz();//饿汉式,创建一个对象 private Cz(){};//构造方法私有化 public static Cz getInstance(){ //提供一个公共方法来创建实例,由该类自己创建的实例 return cz; } public static void main(String[] args) { Cz c1 = Cz.getInstance(); //创建实例 Cz c2 = Cz.getInstance(); System.out.println(c1==c2); //true 判断两个实例是否指向同一个对象 } }
懒汉式:延迟加载,线程不安全
特点:实现了延迟加载,在多线程可能会出现问题不能保证线程安全
public class Cz { //静态全局变量,内存唯一,创建一个对象出来 private static Cz cz = null;//创建一个私有对象 private Cz(){}//创建私有构造方法 public static Cz getInstance(){ if (cz == null){ cz = new Cz(); } return cz; } public static void main(String[] args) { Cz c1 = Cz.getInstance(); Cz c2 = Cz.getInstance(); System.out.println(c1 == c2); } }
静态内部类单例设计模式:延迟加载+线程安全 一般被称之为Holder
特点:用更少的代码达到延迟加载,由于内部类在编译完成之后也是一个单独的class文件,因此在不使用的情况下SingletonHolder类是不会被加载的,同时jvm在加载在过程中static代码块在多线程或单线程下都正确执行,仅执行一次就解决了延迟加载和线程安全
public class Cz { //静态方法私有化 private Cz(){} //静态内部类 private static class SingletonHolder{ private static Cz cz = new Cz(); } //提供公共方法创建单例对象 public static Cz getInstance(){ return SingletonHolder.cz; } public static void main(String[] args) { Cz c1 = Cz.getInstance(); Cz c2 = Cz.getInstance(); System.out.println(c1 == c2); } }