单例模式分为三类:饿汉式单例,懒汉式单例,登记式单例
单例模式的特点:
1,单例类只能有一个实例
2,单例类必须自己创建自己的唯一实例
3,单例类必须给所有其他对象提供这一实例
单例模式类图
一,懒汉式单例
/*
* 单例模式----懒汉式单例
*
* 在类被加载的时候,唯一实例已经被创建
*
*/
public class LazySingleton {
/*
* 私有静态对象,加载时候不做初始化
*/
private static LazySingleton m_intance=null;
/*
* 私有构造方法,避免外部创建实例
*/
private LazySingleton(){
}
synchronized public static LazySingleton getInstance()
{
if(m_intance==null)
{
m_intance=new LazySingleton();
}
return m_intance;
}
}
二,饿汉式单例
/*
* 单例模式----饿汉式单例
*
* */
public class EagerSingleton {
/*
* 私有的唯一实例成员,在类加载的时候就创建好了单例对象
* */
private static final EagerSingleton m_instance=new EagerSingleton();
/*
* 私有构造方法,避免外部创建实例
* */
private EagerSingleton(){}
/*
* 静态工厂方法,返回此类的唯一实例
* */
public static EagerSingleton getInstance()
{
return m_instance;
}
}
三,登记式单例
import java.util.HashMap;
import java.util.Map;
/*
* 单例模式----登记式单例
*
* 这个单例实际上维护的是一组单例类的实例,将这些实例存放在一个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(){}
/*
* 静态工厂方法,返回指定登记对象的唯一实例
* 对于已登记的直接取出返回,对于未登记的,先登记,然后取出返回
* */
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);
}
}
懒汉式单例类实现里对静态工厂方法使用了同步化,以处理多线程环境,同样,由于构造子是私有的,因此,此类不能被继承。饿汉式单例类在自己被加载时就将自己实例化。即便加载器是静态的,在饿汉式单例类被加载时仍会将自己实例化。单从资源利用效率角度来讲,这个比懒汉式单例类稍差些。从速度和反应时间角度来讲,则比懒汉式单例类稍好些。然而,懒汉式单例类在实例化时,必须处理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费时间。这意味着出现多线程同时首次引用此类的机率变得较大。