Java设计模式之单例模式
2016-06-25 23:38
543 查看
Java设计模式之单例模式
1、定义:确保一个类只有一个实例,并提供一个全局的访问点2、关键点:
- 构造函数不对外开放,一般为private
- 通过一个静态方法或者枚举返回单例类对象
- 确保单例类的对象只有一个,尤其是在多线程环境下
- 确保单列类在反序列化的时候不会构建新的对象
3、常见写法:
简单模式
public class Singleton{ private static final Singleton mInstance = new Singleton(); private Singleton(){} public static Singleton getInstance() { return mInstance; } }
简单模式在类加载时就把实例初始化完成了,当需要调用此实例的时候,直接返回mInstance。
懒汉模式
public class Singleton{ private static final Singleton mInstance; private Singleton(){} public static synchronized Singleton getInstance() { if(mInstance == null) { mInstance = new Singleton(); } return mInstance; } }
懒汉模式就是延迟类的初始化到需要的时候,当调用getInstance的时候才会真正的初始化该类。为了防止在多线程环境中产生多个实例,需要在getInstance方法上添加同步关键字synchronized。但是频繁使用synchronized会增加性能消耗。
双重检查锁方式
public class Singleton{ private static final volatile Singleton mInstance; private Singleton(){} public static Singleton getInstance() { if(mInstance == null) { synchronized(Singleton.class) { if(mInstance == null) { mInstance = new Singleton(); } } } return mInstance; } }
双重检查锁方式既延迟初始化又避免了不必要的同步,但是由于构建实例并不是原子操作,所以在复杂的多线程环境下,仍有可能产生多个实例或者实例初始化错误的情况发生(尽管概率很低),所以我们在全局变量mInstance前面增加了volatile关键字,保证了mInstance对象每次都是从主内存中读取。
更优雅的写法-内部静态类
public class Singleton{ private Singleton() { } private static class SingletonHolder{ private static final Singleton mInstance = new Singleton(); } public static Singleton getInstance() { return SingletonHoldler.mInstance; } }
延迟初始化,因为只有当调用getInstance方法的时候才会导致虚拟机加载SingletonHolder类。
确保线程安全并保证单例对象的唯一性,因为一个类只有可能被加载一次。
注意:上述写法在绝大多数情况下是可能保证单例对象唯一性的,但有一种情况除外—–反序列化。通过序列化可以将一个对象写到磁盘上,然后再读取回来。即使构造函数是私有的,反序列化依然可以通过特殊途径去创建类的一个新的实例。解决方法就是在类中添加readResolve()方法,它是一个钩子函数,可以让开发人员控制对象的反序列化。
private Object readResolve() throws ObjectStreamException { return instance; }
枚举单例
public enum SingletonEnum { INSTANCE; public void doSomething() { } }
枚举单例的方式是最简单的,也是最安全的(默认枚举实例的创建时线程安全的),并且没有序列化和反序列化的问题。
基于容器实现的单例
public class SingletonManager { private static final Map<String, Object> objMap = new HashMap(); private SingletonManager(){} static { //类初始化时将多个单例注入到这个管理类中 registerService(key1, instance1); ... } public static void registerService(String key, Object instance) { objMap.put(key, instance); } public static Object getService(String key) { return objMap.get(key); } }
使用容器类存储单例,可以管理多种单例,并且在使用时通过统一的接口进行获取操作,降低用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。
相关文章推荐
- .NET c# 单体模式(Singleton)
- php实现singleton()单例模式实例
- 深入理解线程安全与Singleton
- .Net 单例模式(Singleton)
- Python下singleton模式的实现方法
- Python使用metaclass实现Singleton模式的方法
- 我理解的--java 单例模式
- 我理解的--java工厂模式
- 我理解的--java建造者模式
- 我理解的--java组合模式
- 我理解的--java门面模式
- 我理解的--java策略模式
- 我理解的--java模板方法模式
- 我理解的--java观察者模式
- 我理解的--java备忘录模式
- 我理解的--java中介者模式
- Java设计模式(一) 简单工厂模式不简单
- Java设计模式(十一) 享元模式
- Java设计模式(二) 工厂方法模式