Effective Java (3) - 用私有构造器或者枚举类型强化Singleton属性

一、背景

所谓的Singleton是指仅仅被实例化一次的类,Singleton通常被用来代表那些本质上唯一的系统组件。

实现Singleton有以下三种方法:

①. 私有构造器,公有静态final域。

②. 私有构造器,公有静态工厂方法。

③. 单元素枚举类型(首选)。


二、私有构造器,公有静态final域

public class Singleton1 {

	public static final Singleton1 INSTANCE = new Singleton1(); // 公有静态final域

	/*
	 * 私有构造器
	 */
	private Singleton1() {
	}

}

三、私有构造器,公有静态工厂方法

缺点1:享有特权的客户端可以借助AccessibleObject.setAccessible方法,通过反射机制,调用私有构造器,如果需要抵御这种攻击,可以修改构造器,让它在被要求创建第二个实例的时候抛出异常。

public class Singleton2 {
	private static final Singleton2 INSTANCE = new Singleton2(); // 私有静态final域

	/*
	 * 私有构造器
	 */
	private Singleton2() {
	}

	/*
	 * 公有静态工厂方法
	 */
	public static Singleton2 getInstance() {
		return INSTANCE;
	}

}


缺点2:每次反序列化一个序列化的实例时,都会创建一个新的实例,为了防止这种情况,不仅要实现Serializable接口,还要提供一个readResolve方法。

public class Singleton2 implements Serializable {
	private static final long serialVersionUID = 1L;
	private static final Singleton2 INSTANCE = new Singleton2(); // 私有静态final域

	/*
	 * 私有构造器
	 */
	private Singleton2() {
	}

	/*
	 * 公有静态工厂方法
	 */
	public static Singleton2 getInstance() {
		return INSTANCE;
	}

	/*
	 * 反序列化确保只有一个实例
	 */
	public Object readResolve() {
		return INSTANCE;
	}

}

四、单元素枚举类型

最佳方法:更简洁,无偿提供序列化机制,绝对防止多次实例化,即使是面对复杂的序列化或反射攻击的时候。

public enum Singleton3 {
	INSTANCE;
	
	public void testSingleton() {
		System.out.println("testSingleton");
	}

	public static void main(String[] args) {
		Singleton3.INSTANCE.testSingleton();
	}
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值