单例模式确保一个类只有一个实例,且自行实例化并向整个系统提供这个实例。
单例模式特点:
- 单例类只能有一个实例
- 单例类必须自己创建自己的实例
- 单例类必须给其它对象提供这个实例
单例模式中单例类实现方式:
饿汉式实现
package com.create.single; /** * * 饿汉式单例 * @date 2013-11-26 */ public class Singleton { private final static Singleton singleton = new Singleton(); private Singleton(){ } public static Singleton getInstance(){ return singleton; } }
懒汉式实现
package com.create.single; /** * * 懒汉式单例创建 * @date 2013-11-26 */ public class LazySingleton { private static LazySingleton singleton; private LazySingleton(){ } synchronized public static LazySingleton getInstance(){ if(singleton==null){ singleton = new LazySingleton(); } return singleton; } }
登记式实现
package com.create.single; import java.util.HashMap; import java.util.Map; /** * 登记式单例类 * 该种方式实现克服饿汉式与懒汉式单例类实现方式不能被继承的缺点 * @date 2013-11-26 */ public class RegSingleton { private static Map<String,RegSingleton> reg = new HashMap<String, RegSingleton>(); static{ RegSingleton singleton = new RegSingleton(); reg.put(singleton.getClass().getName(), singleton); } protected RegSingleton(){ } public static RegSingleton getInstance(String name){ if(name==null){ name = "com.create.single.RegSingleton"; } if(reg.get(name)==null){ try { Object obj = Class.forName(name).newInstance(); reg.put(name, (RegSingleton)obj); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return reg.get(name); } }
package com.create.single; /** * * 登记式实现子类 * @date 2013-11-26 */ public class RegSingletonChild extends RegSingleton{ public RegSingletonChild(){ } public static RegSingletonChild getInstance(){ return (RegSingletonChild)RegSingleton.getInstance("com.create.single.RegSingletonChild"); } }
通过以上的实现方式可以看出,饿汉式与懒汉式实现构造函数都是私有的,该类不能够被继承;但是饿汉式实现是静态方式实例化,但从资源角度来看,饿汉式稍微差些,从反应时间和效率来看比懒汉式要好。登记式实现克服单例类不能被继承的缺点。
单例类的状态
(1)一个单例类是可以有状态的,有状态的单例类也可以是可变的单例对象。比如一个单例可以有int属性,当然单例也可以有个聚集属性,可以存储多个状态
(2)单例类也可以没有状态,仅作为工具性函数。
注:多个JVM的分布式系统与多个类加载器是不适合有状态的单例的。
建议:使用恶汉式单例模式或者静态工厂同步的懒汉式单例模式已经满足需求。