文章转载自:http://zengzhaoshuai.iteye.com/blog/1121081
一、单例模式要点
1.单例,顾名思义,某个类只能有一个实例。2.它必须自行创建这个唯一的实例。
3.它必须自行向整个系统提供这个实例。
二、单例模式的三种实现
1.饿汉式单例类(类加载时就初始化)
- public class EagerSingleton {
- //私有的类成员常量
- private static final EagerSingleton SINGLETON=new EagerSingleton();
- //私有的默认构造方法,此类不能被继承
- private EagerSingleton(){}
- //静态工厂方法
- public static EagerSingleton getInstance(){
- return SINGLETON;
- }
- }
Java语言中的单例类的一个最重要的特点是类的构造方法是私有的,从而避免外界利用构造方法直接创建出人意多飞实例。
2.懒汉式单例类(第一次调用才初始化,延迟)
- public class LazySingleton {
- private static LazySingleton singleton=null;
- //私有的默认构造方法,此类不能被继承
- private LazySingleton(){}
- //同步,静态工厂方法,返回此类的唯一实例
- public synchronized static LazySingleton getInstance(){
- if(singleton==null){
- singleton=new LazySingleton();
- }
- return singleton;
- }
对2的懒汉式的另外一种改进
- public class DoubleCheckSingleton {
- private volatile static DoubleCheckSingleton singleton = null;
- // 私有的默认构造方法,此类不能被继承
- private DoubleCheckSingleton() {
- }
- // 静态工厂方法,返回此类的唯一实例
- public static DoubleCheckSingleton getInstance() {
- if (singleton == null) {
- synchronized (DoubleCheckSingleton.class) {
- if (singleton == null) {
- singleton = new DoubleCheckSingleton();
- }
- }
- }
- return singleton;
- }
- }
3.登记式单例类
登记式单例类是为了克服饿汉式单例类和懒汉式单例类不可继承的缺点而设计的。
- package com.zzs.singleton;
- import java.util.HashMap;
- public class RegSingleton {
- private static HashMap registry=new HashMap();
- /**静态代码块
- *静态代码块优先于主方法执行,而在类中定义的静态代码会优先于构造块执行,而且不管产生多少对象,静态代码块只执行一次。
- */
- static{
- RegSingleton singleton=new RegSingleton();
- registry.put(singleton.getClass().getName(), singleton);
- }
- protected RegSingleton(){}
- public static RegSingleton getInstance(String name){
- if(name==null){
- name="com.zzs.singleton.RegSingleton";
- }
- if(registry.get(name)==null){
- try {
- registry.put(name, Class.forName(name).newInstance());
- } catch (InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return (RegSingleton) registry.get(name);
- }
- }
- package com.zzs.singleton;
- public class RegSingletonChild extends RegSingleton {
- //由于子类必须允许父类以构造方法调用产生实例,所以它的构造方法必须是公开的,protected或public
- protected RegSingletonChild() {
- }
- //静态方法工厂
- public static RegSingletonChild getInstance() {
- return (RegSingletonChild) RegSingleton
- .getInstance("com.zzs.singleton.RegSingletonChild");
- }
- }
三、在什么情况下使用单例模式
使用单例模式的一个必要条件:在一个系统中要求只有一个类的实例时应当使用单例模式。反过来说,如果一个类可以有几个实例共存,那么就没有必要使用单例类。java语言中的Runtime对象就是一个单例模式。