Effective Java -- 创建和销毁对象 -- 用私有构造器或者枚举类型强化Singleton属性(单例模式)

第二章 创建和销毁对象

第三条 用私有构造器或者枚举类型强化Singleton属性

Singleton是指仅仅被实例化一次的类(也就是单例模式)。

需要满足:

  1. 只能有一个实例。
  2. 必须自己创建自己的唯一实例(构造方法私有)。
  3. 必须给所有其他对象提供这一实例。

一 实现Singleton两种常见方法

1 公有的不可变静态成员

一个孙悟空单例类:
(原文是Elvis即猫王,个人对猫王不熟悉,所以这里就用孙悟空代替好了)

/*孙悟空类*/
public class WuKong {
	//公有的静态不可变域来提供实例
    public static final WuKong INSTANCE = new WuKong();
	//私有的构造方法仅被调用一次
    private WuKong() {
    }
}

优点:比较简单

2 公有的静态工厂方法
/*孙悟空类*/
public class WuKong {
	//私有的静态不可变域
    private static final WuKong INSTANCE = new WuKong();
	//私有的构造方法仅被调用一次
    private WuKong() {
    }
    //公有的静态工厂方法返回实例
    public static WuKong getInstance() {
        return INSTANCE;
    }
}

优点:
易于取消Singleton
可以编写泛型Singleton工厂(详见第30条)
可以通过方法引用作为提供者(不太懂)

3 注意反射攻击

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

4 序列化问题

这两种方法如果只是implements Serializable是不够的,每次反序列化一个序列化的实例时,都会创建一个新的实例(六耳猕猴?)。为了防止这种情况,要在WuKong类中加入readResolve方法:

	private Object readResolve(){
        return INSTANCE;
    }

这样就可以保证反序列化时也同时是singleton了。(具体原理不是很清楚,可以看 这个帖子 的解释)

二 实现Singleton第三种方法

1 实例

声明一个包含单个元素的枚举类型:

/*孙悟空类*/
public enum WuKong {
    INSTANCE;
}
2 优点

这种方法十分简洁,且避免了序列化问题和反射攻击。

三 总结

单元素的枚举类型是实现Singleton的最佳方法。
但如果Singleton必须继承一个超类而不是继承一个枚举类时,则不宜使用这个方法(虽然可以声明枚举去实现接口(这里书中没有细说,日后再深入了解一下))。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值