本文共 3280 字,大约阅读时间需要 10 分钟。
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
对一些类来说,只有一个类实例是很重要的,比如一个公司CEO只有一位,一个帝国只有一个皇帝。
单例模式是应用最广的模式之一,单例对象的类必须保证只有一个实例存在。如在一个应用中,应该只有一个ImageLoader实例,这个ImageLoader中又含有线程池,缓存系统,网络请求等,很消耗资源,因此,没有理由让它构造多个实例。保持只有一个单例,好的办法是让类自身负责保存它的唯一实例。
确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例
public class Singleton { private void Singleton(){} private static Singleton instance =new Singleton(); public static Singleton getInstance(){ return instance; }}
加载类的时候就构造了单例,有个问题是万一客户端一直都不用这个单例呢,岂不是浪费资源
public class Singleton { private void Singleton(){} private static Singleton instance; public static synchronized Singleton getInstance(){ if (instance==null) { instance=new Singleton(); } return instance; }}
这里getInstance()方法添加了synchronized关键字,也就是getInstance()是一个同步方法,目的是保证在多线程情况下单例对象唯一的手段。这里会有个问题,即使instance已经被初始化,每次调用getInstance()方法都会进行同步,这样会消耗不必要的资源。
public class Singleton { private void Singleton(){} private static Singleton instance=null; public static Singleton getInstance(){ if (instance==null) { synchronized (Singleton.class){ if(instance==null){ instance=new Singleton(); } } } return instance; }}
因为getInstance()可能同时会有多个客户端调用,DCL方式实现单例模式的优点是既能在需要时才初始化单例,又能保证线程安全,且单例对象初始化调用后调用getInstance不进行同步锁。
这种实现方式很流行,很多框架都用这种
public class Singleton { private void Singleton(){} public static Singleton getInstance(){ return SingletonHolder.sInstance; } /** * 静态内部类 */ private static class SingletonHolder{ private static final Singleton sInstance=new Singleton(); }}
DCL虽然在一定程度上解决了资源消耗,多余的同步,线程安全等问题,但是,他还是在某些情况下出项失效的问题。
静态内部类单例模式,当第一次加载Singleton类时并不会初始化sInstance,只有在第一次调用Singleton的getInstance方法时才会导致sInstance被初始化。因此,第一次调用getInstance方法会导致虚拟机加载SinglentonHolder类,这种方式不仅能确保线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化,所以这个是推荐使用的单例模式实现方式。
public enum SingletonEnum { INSTANCE; public void dosomeThing(){ System.out.println("do sth."); }}
《Effective Java》推荐的用法,用枚举
public class SingletonManager { private static MapobjMap=new HashMap (); private SingletonManager(){} public static void registerService(String key,Object instance){ if (!objMap.containsKey(key)) { objMap.put(key, instance); } } public static Object getService(String key){ return objMap.get(key); }}
在程序的初始,将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对象对应类型的对象。
// todo 这个很常见了,后面贴个代码
// todo 待研究,后面更
转载地址:http://nrkdm.baihongyu.com/