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、单例对象占用资源大需要延时加载:静态内部类好于懒汉式。

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值