单例模式的最佳实践
好记性不如烂笔头,总结一下自己印象深刻的设计模式,从最简单的单例模式开始吧!
简介单例模式(Singleton Pattern) 是最简单的设计模式之一了,这种类型的设计模式属于创建者模式,这种模式是为了确保只有一个对象被创建。
特点:
- 单例类只能有一个实例
- 单例类必须自己创建自己的唯一实例
- 单例类必须给其他对象提供着一种实例
优点:
- 内存中只有该类的一个实例,避免全局使用的类频繁的创建销毁,浪费系统资源。
- 避免对资源的多重占用(写文件操作,避免对文件多重占用)。
缺点:
没有接口,不能继承,与单一职责冲突,一个类应该只关心内部逻辑,不关心外面怎样实例化。
1.饿汉模式
优点:线程安全,不加锁,执行效率高。
缺点:类装载时实例化, 不能保证lazy load 效果,浪费内存。
注意:
- 基于 classloder 机制避免了多线程的同步问题
- 如果调用 getInstance 方法时导致类加载,满足lazy load 载效果。
代码:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){}
public static getInstance(){
return instance;
}
}
2. 懒汉模式(double-checked locking)
优点 lazy load,线程安全且保持高性能
缺点 ,实现较复杂
代码:
public class Singleton {
// volatile 保证 new 原子性
private volatile static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
// 双校验
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
3. 静态内部类模式
优点:lazy, 线程安全,实现简单,跟双检锁方式效果效果相同
注意:
利用 classloder 机制保证初始化一个instance只有一个线程。
代码:
public class Singleton {
private Singleton(){}
// 静态内部类
private static class SingletonFactory {
peivate static final Singleton INSTANCE = new Singleton();
}
public static final Singleton getIntance() {
return SingletonFactory.INSTANCE;
}
}
4. 枚举
优点:线程安全,简洁,自动支持序列化机制,绝对防止多次序列化,防止反序列化重新创建新的对象。
缺点: no lazy, 不能通过 reflection attack 调用私有构造。
代码:
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
总结
经验之谈:
- 建议使用 1.饿汉模式 加载
- 明确需要 lazy load 使用 3.内部类模式
- 涉及反序列化创建对象,使用 4.枚举
- 有其他需求,考虑 2.双检锁懒汉模式