Java 常用设计模式之单例模式

本文详细介绍了Java中的单例模式,包括饿汉式、懒汉式、静态内部类和枚举实现,强调了线程安全与性能的权衡。同时,讨论了如何防止单例模式被反射和序列化破坏,提供了相应的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言
初学总结,如有问题还请大家指正
单例模式的使用场景
需要频繁的进行创建和销毁对象时,但又要经常使用到的对象、工具类对象、频繁访问数据库或文件的对象(比如 数据源、session  工厂等),
由于耗时过多或耗费资源过多从而使用单例模式.

一、单例模式创建

1.饿汉式

定义:
	饿汉式构建是一种以空间换取时间的方式,
	在类装载结束后,实例就会被创建出来,不管你用或者不用它就在那里,
	在之后的使用中,直接进行调取即可无需判断.
优点:
	线程安全,容易实现
缺点:
	初始化时速度较慢
public class Singleton {

   //创建 SingleObject 的一个对象
   private static Singleton instance = new Singleton ();

   //让构造函数为 private,这样该类就不会被实例化
   private Singleton (){}

   //获取唯一可用的对象
   public static Singleton getInstance(){
      return instance;
   }
}

2.懒汉式

定义: 
	与饿汉式相反,懒汉式采取的是时间换空间的方式,
	体现了缓存的思想,**延时加载**就是一开始不要加载资源或者数据,
	一直等到马上就要使用这个资源或者数据了,在开始创建对象.
优点:
	初始化速度较快
缺点:
	在不加同步的时候,是线程不安全的
public class Singleton {
	
	// 1.先创建一个null对象实例
	private static Singleton instance = null;
 
	 // 2.让构造函数为 private,这样该类就不会被实例化
	private Singleton() {}
 
    // 3.提供一个公有的静态方法,返回实例对象
	public static Singleton getInstance() {
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

实现线程安全懒汉式(双重加锁校验)

public class Singleton {
	private volatile static Singleton instance = null;
 
	// 私有化构造方法
	private Singleton() {
 
	}
 
	public static Singleton getInstance() {
		if (instance == null) {
			synchronized (Singleton.class) {
				if (instance == null) {
					instance = new Singleton();
				}
			}
 
		}
		return instance;
	}
 
}

3.使用静态内部类

public class Singleton {
	private static class SingletonHoler {
		/**
		 * 静态初始化器,由JVM来保证线程安全
		 */
		private static Singleton instance = new Singleton();
	}
 
	private Singleton() {
	}
 
	public static Singleton getInstance() {
		return SingletonHoler.instance;
	}
}

当getInstance方法第一次被调用的时候,它第一次读取SingletonHolder.instance,导致SingletonHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性.

4.枚举

public enum Singleton {
	uniqueInstance;// 定义一个枚举的元素,它 就代表了Singleton的一个实例
 
	public void singletonOperation() {
		// 功能处理
		System.err.println("功能处理");
	}
}

二、防止破坏单例模式

  1. 反射
    定义一个全局变量,当第二次创建的时候抛出异常
  2. 反序列化
**
 * 序列化对单例的破坏,解决方案
 * @author IT_LittleBaby
 *
 */
public class SingletonTest10 {
	
	public static void main(String[] args) throws Exception{
		
		System.out.println("-----------序列化----------------------");
	     Singleton originSingleton = Singleton.getInstance();
	     ByteArrayOutputStream bos = new ByteArrayOutputStream();
	     ObjectOutputStream oos = new ObjectOutputStream(bos);
	      oos.writeObject(Singleton.getInstance());
	      ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
	      ObjectInputStream ois = new ObjectInputStream(bis);
	      Singleton serializeSingleton = (Singleton) ois.readObject();
	      System.out.println(originSingleton == serializeSingleton);//false
	      
	      System.out.println("-----------反射----------------------");
	      //通过反射获取
	        Constructor<Singleton> cons = Singleton.class.getDeclaredConstructor();
	        cons.setAccessible(true);
	        Singleton reflextSingleton = cons.newInstance();
	        System.out.println(reflextSingleton == originSingleton);//false
	        
	        System.out.println("---------------------------克隆----------------------");
	        
	        Singleton cloneSingleton = (Singleton) originSingleton.clone();
	        System.out.println(cloneSingleton == originSingleton);//false
	}
}
 
  1. 克隆
    添加readResolve(),返回Object对象
private static class Singleton  implements Serializable,Cloneable{
		
		private static volatile boolean isCreate = false;//默认是第一次创建
		/**
		 * 1.构造方法私有化,外部不能new
		 */
		private Singleton() {
			if(isCreate) {
				throw new RuntimeException("已然被实例化一次,不能在实例化");
			}
			isCreate = true;
		}
		
		//2.本类内部创建对象实例
		private static  volatile  Singleton instance;
		
		//3.提供一个公有的静态方法,返回实例对象
		public static  Singleton getInstance() {
			if(instance == null) {
				synchronized (Singleton.class) {
					if(instance == null) {
						instance = new Singleton();
					}
				}
			}
			return instance;
		}
		
		@Override
		 protected Object clone() throws CloneNotSupportedException {
		     return instance;
		 }
		
		/**
		 * 防止序列化破环
		 * @return
		 */
		private Object readResolve() {
	        return instance;
	    }
		 
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Karma's a Bitch

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值