GOF设计模式之单例模式

Posted 寒松,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GOF设计模式之单例模式相关的知识,希望对你有一定的参考价值。

GOF设计模式之单例模式

单例模式即保证类只有一个实例,并且提供一个访问该实例的全局访问点。定义一个类,将其属性私有化、构造器也私有化,只留下一个方法给外部调用。比较适用调用和销毁频繁的类、一些工具类对象、创建时耗时或者占用资源又不得不用的类、一些访问频繁的数据库和文件对象。

其五种写法

一、懒汉式

public class Singleton 
	//类初始化时,立即加载这个对象(没有延时加载的优势),类加载是天然的线程安全
	private static Singleton instance = new Singleton();
	
	private Singleton()		
	 
	//方法没有同步,调用效率高
	public static Singleton getInstance() 
		return instance;
	

二、饿汉式

public class Singleton 
	//类初始化时,不初始化(延时加载,到要用的时候在加载)
	private static Singleton instance;
	
	private Singleton()		
	
	//方法同步,调用效率低
	public static synchronized Singleton getInstance() 
		if(instance == null ) 
			instance  = new Singleton();
		
		return instance ;
	

三、双重检测锁式

public class Singleton 
		
	private static Singleton instance  = null;
	
	public static Singleton getInstance() 
	/*虽然也添加了同步块,但是同步块再if之下,只有第一次才
	 * 进行同步,不必每次获取对象都进行同步,提高了执行效率。*/
		if(instance  ==null) 
			Singleton sc;
			synchronized (Singleton.class) 
				sc = instance  ;
				synchronized (Singleton.class) 
					if(sc == null) 
						sc = new Singleton();
					
				
				instance  = sc;
					
		
		return instance ;
			
	private Singleton() 		
	

//由于编译器优化原因和JVM底层内部模型原因,偶尔回出现问题,慎用!

四、静态内部类式

public class Singleton 
//调用此方法时才创建对象且线程安全,并且实现了延时加载,调用效率高。
	private static class SingletonClassInstance
		private static final Singleton instance = new Singleton();
	
	
	private Singleton() 	
	
	
	public static  Singleton getInstance() 
	
		return SingletonClassInstance.instance;
	 

五、枚举式

public enum Singleton 
	//这个枚举本身就是一个单例对象,且天然线程安全,但是无法延时加载
	INSTANCE;
	//可以添加自己需要的操作
	public void SingletonOperation() 		
	 

如何避免反射漏洞

首先需要了解时怎么通过反射漏洞的,就是调用了**.setAccessible(true);**方法使其跳过权限检查,从而可以直接访问其私有的成员,从二直接创建对象。如何避免呢?可以直接在类内部私有无参构造器中添加一个判断即可

private Singleton()
		//判断instance是否创建,如果不为空直接抛出异常即可。
		if(instance != null) 
			throw new RuntimeException();
		
	

如何避免反序列化漏洞

反序列化漏洞是将已经创建的类对象通过序列化存储到文件中,再通过反序列化将文件读取,从而创建一个新的类对象。避免方法即在类中添加下面这个私有方法

//反序列化时,如果创建了readResolve()则直接返回此方法指定的对象,不需要再创建新对象
	private Object readResolve() 
		return instance;
	

如何选用

1、单例对象如果占用资源少不需要延时加载:枚举比饿汉式好;
2、单例对象占用资源大需要延时加载:静态内部类好于懒汉式。

学习笔记,如有不对的地方,烦请大神帮忙指点指点!

以上是关于GOF设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

GOF设计模式之单例模式

GOF设计模式之单例模式

GOF23设计模式之单例模式

Java设计模式GOF之单例模式

GOF设计模式之单例模式

GOF23设计模式之单例模式(singleton)