设计模式之单例模式(四)
单例模式有三种:懒汉式单例、饿汉式单例、登记式单例三种
一、懒汉式单例
在类被加载的时候,唯一实例已经被创建。这个设计模式在Java中容易实现,在别的语言中难以实现。
public class LazySingleton { /** * 私有静态对象,加载时候不做初始化 */ private static LazySingleton m_intance=null; /** * 私有构造方法,避免外部创建实例 */ private LazySingleton(){ } /** * 静态工厂方法,返回此类的唯一实例. * 当发现实例没有初始化的时候,才初始化. * @return LazySingleton */ synchronized public static LazySingleton getInstance(){ if(m_intance==null){ m_intance=new LazySingleton(); } return m_intance; } }
二、饿汉式单例
在类加载的时候不创建单例实例。只有在第一次请求实例的时候的时候创建,并且只在第一次创建后,以后不再创建该类的实例。
public class EagerSingleton { /** * 私有的(private)唯一(static final)实例成员,在类加载的时候就创建好了单例对象 */ private static final EagerSingleton m_instance = new EagerSingleton(); /** * 私有构造方法,避免外部创建实例 */ private EagerSingleton() { } /** * 静态工厂方法,返回此类的唯一实例. * @return EagerSingleton */ synchronized public static EagerSingleton getInstance() { return m_instance; } }
三、登记式单例
这个单例实际上维护的是一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从工厂直接返回,对于没有登记的,则先登记,而后返回。
public class RegSingleton { /** * 登记薄,用来存放所有登记的实例 */ private static Map<String, RegSingleton> m_registry = new HashMap(); //在类加载的时候添加一个实例到登记薄 static { RegSingleton x = new RegSingleton(); m_registry.put(x.getClass().getName(), x); } /** * 受保护的默认构造方法 */ protected RegSingleton() { } /** * 静态工厂方法,返回指定登记对象的唯一实例; * 对于已登记的直接取出返回,对于还未登记的,先登记,然后取出返回 * @param name * @return RegSingleton */ public static RegSingleton getInstance(String name) { if (name == null) { name = "RegSingleton"; } if (m_registry.get(name) == null) { try { m_registry.put(name, (RegSingleton) Class.forName(name).newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return m_registry.get(name); } }
处理好多线程并发才是单例模式的关键 synchronized