设计模式之单例模式Java代码示例
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,属于创建型模式。
核心作用:
- 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
常见场景
- Windows系统任务管理器
- Windows系统回收站
- 项目中,读取配置文件的类,一般也只有一个对象,没必要每次用new实例化对象读取。
- 网站的计数器一般也会采用单例模式,可以保证同步
- 数据库连接池的设计一般也是单例模式
- 在Servlet编程中,每个Servlet也是单例的
- 在Spring中,每个Bean默认就是单例的
- ...........
优点:
- 由于单例模式只生成一个实例,减少了系统性能开销。
- 单例模式可以在系统设置全局的访问点,优化共享资源访问。
- 单例模式可以说是一个合格的开发都会写。但是如果要深究,小小的单例模式可以牵涉到很多东西。
缺点:
- 没有定义接口,不可继承,与单一职责原则相冲突,类只应该关心其内部逻辑,不关心外面怎么去实例化。
如何去保证实例唯一
- 防止类外部被初始化
- 由类自身进行实例化
- 保证类仅实例化一次
- 对外提供获取该实例的唯一方法
- 线程安全
常见的五种单例模式实现方式
饿汉式(线程安全,调用效率高,不能延时加载)
//饿汉式单例 public class SingletonDemo01 { //1.私有化构造器 private SingletonDemo01(){ } //2.类初始化的时候,立即加载该对象 private static SingletonDemo01 instance = new SingletonDemo01(); //3.提供获取该对象的方法,没有synchronized,效率高! public static SingletonDemo01 getInstance(){ return instance; } } class SingletonDemo01Test{ public static void main(String[] args) { SingletonDemo01 instance = SingletonDemo01.getInstance(); SingletonDemo01 instance2 = SingletonDemo01.getInstance(); System.out.println(instance==instance2);//true } }
懒汉式(线程安全,调用效率不高,可以延时加载)
//懒汉式 public class SingletonDemo02 { //1.私有化构造器 private SingletonDemo02(){ } //2.类初始化的时候,不立即加载该对象 private static SingletonDemo02 instance; //3.提供获取该对象的方法,有synchronized,效率较低! public static synchronized SingletonDemo02 getInstance(){ if(instance == null){ instance = new SingletonDemo02(); } return instance; } } class SingletonDemo02Test{ public static void main(String[] args) { SingletonDemo02 instance = SingletonDemo02.getInstance(); SingletonDemo02 instance2 = SingletonDemo02.getInstance(); System.out.println(instance==instance2);//true } }
DCL懒汉式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用)
//DCL 双检锁/双重校验锁(DCL,即 double-checked locking) 懒汉式 public class SingletonDemo03 { private static boolean flag = false; //1.私有化构造器 private SingletonDemo03(){ synchronized (SingletonDemo03.class){ if(flag == false){ flag = true; }else{ throw new RuntimeException("不要试图用反射破坏我们的单例"); } } } //2.类初始化的时候,不立即加载该对象 //volatile 原子性 private volatile static SingletonDemo03 instance; //3.提供获取该对象的方法,有synchronized,效率较低! public static SingletonDemo03 getInstance(){ if(instance == null){ synchronized (SingletonDemo03.class){ if(instance == null){ instance = new SingletonDemo03(); } } } return instance; } } class SingletonDemo03Test{ public static void main(String[] args) throws Exception { Constructor<SingletonDemo03> declaredConstructor = SingletonDemo03.class.getDeclaredConstructor(null); declaredConstructor.setAccessible(true); SingletonDemo03 instance1 = declaredConstructor.newInstance(); SingletonDemo03 instance3 = declaredConstructor.newInstance(); System.out.println(instance1==instance3); System.out.println(instance1.hashCode()); System.out.println(instance3.hashCode()); } }
饿汉式改进:静态内部类(线程安全,调用效率高,可以延迟加载)
//静态内部类实现 public class SingletonDemo04 { private SingletonDemo04(){ } private static class InnerClass{ private static final SingletonDemo04 instance = new SingletonDemo04(); } public static SingletonDemo04 getInstance(){ return InnerClass.instance; } } //反射机制:可以破坏以上的单例 class SingletonDemo04Test{ public static void main(String[] args) throws Exception {//捕获一个大异常Exception SingletonDemo04 instance = SingletonDemo04.getInstance(); Constructor<SingletonDemo04> declaredConstructor = SingletonDemo04.class.getDeclaredConstructor(null); declaredConstructor.setAccessible(true); SingletonDemo04 instance3 = declaredConstructor.newInstance(); System.out.println(instance==instance3); System.out.println(instance.hashCode()); System.out.println(instance3.hashCode()); } }
枚举单例(线程安全,调用效率高,不能延迟加载)
public enum SingletonDemo05 { INSTANCE; public SingletonDemo05 getInstance(){ return INSTANCE; } } class SingleDemo05Test{ public static void main(String[] args) { SingletonDemo05 instance = SingletonDemo05.INSTANCE; SingletonDemo05 instance2 = SingletonDemo05.INSTANCE; System.out.println(instance==instance2); } }
(本篇知识杂柔自互联网,仅供分享学习)