单例模式
- 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式实例需要注意的方面
- 某一个类只有一个实例
- 构造器私有化
- 必须自行创建实例
- 含有一个该类的静态变量来保存这个唯一实例
- 自行向整个系统提供实例
- 对外提供获取该实例对象的方式
- 直接暴露
- 用静态变量的get方法获取
单例模式的分类以及几种常见形式
饿汉式:直接创建对象,不存在线程安全问题
-
直接实例化饿汉式(简洁直观)
/* * 饿汉式: * 直接创建实例对象,不管是否需要,都会创建 * * (1) 构造器私有化 * (2) 自行创建,并且用静态变量保存 * (3) 向外提供实例 * (4) 强调这是一个单例 */ public class SingLeton1 { public static final SingLeton1 INSTANCE = new SingLeton1(); private SingLeton1() { } }
-
枚举式(最简洁)
/* * 枚举类型:表示该类型是有限的几个 * 我们可以限定为一个,就是单例 */ public enum Singleton2 { INSTANCE }
-
静态代码块饿汉式(适合复杂实例化)
/* * 这种方式通常用来加载初始化数据,或者加载配置文件中的数据 * * */ public class Singleton3 { public static final Singleton3 INSTANCE; private String info; static{ try { Properties pro = new Properties(); pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties")); INSTANCE = new Singleton3(pro.getProperty("info")); } catch (IOException e) { throw new RuntimeException(e); } } private Singleton3(String info){ this.info = info; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public String toString() { return "Singleton3 [info=" + info + "]"; } }
懒汉式:延迟创建对象
-
线程不安全(适用于单线程)
/* * 懒汉式: 延迟创建这个实例对象 * (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 Singleton4 { private static Singleton4 instance; private Singleton4() { } public static Singleton4 getInstance() { if(instance == null) { synchronized (Singleton4.class) { if(instance == null) { try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } instance = new Singleton4(); } } } return instance; } }
-
静态内部类形式(适用于多线程 )
/* * 在内部类被加载和初始化时,才创建INSTANCE实例对象 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。 * 因为是在内部类加载和初始化时,创建的,因此是线程安全的 */ public class Singleton6 { private Singleton6(){ } private static class Inner{ private static final Singleton6 INSTANCE = new Singleton6(); } public static Singleton6 getInstance(){ return Inner.INSTANCE; } }