单例模式
定义
Ensure a class has only one instance, and provide a global point of access to it.
通用类图是:
通用代码是:
public class Singleton {
private static final Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getSingleton(){
return singleton;
}
}
单例模式应用
优点
- 减少内存开支,特别是对象需要频繁的创建、销毁时
- 减少系统性能的开销,当对象的产生需要比较多的资源,可以在启动时直接产生一个单例对象的方式来解决
- 避免对资源的多重占用
- 可以在系统设置全局的访问点,优化和共享资源。。。
缺点
- 一般没有接口,扩展困难
- 对测试时不利的
- 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心它是否是单例的,是不是单例取决于环境,单例模式把“要单例”和业务逻辑融合在一个类中了。
使用场景
- 要求生成唯一序列号的环境
- 在整个项目中需要一个共享访问点或共享数据,例如一个Web页面的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保线程安全即可
- 创建一个对象需要消耗较多的资源,如访问IO和数据库等
- 需要定义大量的静态常量和静态方法的环境,可以采用单例模式
注意问题
- 线程安全问题
- 考虑对象的赋值情况,对象复制是不调用类的构造函数的
多种单例实现
-
懒汉式(延迟加载)
public class Singleton{ private static Singleton singleton; private Singleton() { } public synchronized static Single newInstance() { if (singleton== null) { singleton= new Singleton(); } return singleton; } }
标准的单例模式,通过newInstance里面的判断来进行延迟加载单例对象,这里加了synchronized关键字可以避免多线程问题,但会影响程序性能。
-
饿汉式(贪婪加载)
public class Singleton { private static Singleton singleton= new Singleton(); private singleton() { } public static Singleton newInstance() { return singleton; } }
在单例对象声明的时候就直接初始化对象,可以避免多线程问题,但是如果对象初始化比较复杂,会导致程序初始化缓慢。
-
双重检查加锁
public class Singleton { private volatile static Singleton singleton; private Singleton() { } public static Singleton newInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
这个是懒汉形式的加强版,将synchronized关键字移到了newInstance方法里面,同时将singleton对象加上volatile关键字,这种方式既可以避免多线程问题,又不会降低程序的性能。但volatile关键字也有一些性能问题,不建议大量使用。
-
内部静态类
public class Singleton { private static class SingletonHolder { private static Singleton singleton = new Singleton(); } private Singleton() { } public static Singleton newInstance() { return SingletonHolder.singleton; } }
通过内部类的机制使得单例对象可以延迟加载,同时内部类相当于是外部类的静态部分,所以可以通过jvm来保证其线程安全。这种形式比较推荐。
-
枚举类
public enum Singleton { singleton }
的机制使得单例对象可以延迟加载,同时内部类相当于是外部类的静态部分,所以可以通过jvm来保证其线程安全。这种形式比较推荐。
-
枚举类
public enum Singleton { singleton }
最推荐的方法。