单例模式

来源:互联网 发布:java 开源权限框架 编辑:程序博客网 时间:2024/06/11 00:12

1. 单例模式的定义:
Ensure a class has only one instance, and provide a global point of access to it。(保证一个类仅有一个实例,并提供一个访问它的全局访问点。)
2. 单例模式结构图:
这里写图片描述
 3. 单例模式写法:
(1)饿汉模式:

public class Singleton {       private static Singleton instance = new Singleton();       private Singleton (){     }     public static Singleton getInstance() {       return instance;       }   }  
优点:类加载时就完成了初始化,获取对象的速度快,基于类加载机制避免了多线程的同步问题。
缺点:类加载较慢,由于不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。
(2)懒汉模式(线程不安全)
public class Singleton {        private static Singleton instance;        private Singleton (){      }         public static Singleton getInstance() {            if (instance == null) {                instance = new Singleton();            }            return instance;        }   }  
优点:懒汉模式申明了一个静态对象,在用户第一次调用时初始化,节约了资源;
缺点:第一次加载时需要实例化,反映稍慢一些;并且在多线程不能正常工作。
(3)懒汉模式(线程安全)
public class Singleton {        private static Singleton instance;        private Singleton (){      }      public static synchronized Singleton getInstance() {            if (instance == null) {                instance = new Singleton();            }            return instance;        }   }  
优点:多线程下能够比较好的工作;
缺点:每次调用getInstance方法时都需要进行同步,造成不必要的同步开销。
(4)双重检查模式(DCL)
public class Singleton {  /*对保存实例的变量添加volatile修饰,被volatile修饰的变量,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而保证多个线程能正确的使用该变量。*/ private volatile static Singleton singleton;        private Singleton (){      }         public static Singleton getInstance() {  //先检查实例是否存在,不存在才进入下面的同步块        if (instance== null) {            //同步块,线程安全的创建实例          synchronized (Singleton.class) {  //再次检查实例是否存在,不存在才真正的创建实例          if (instance== null) {                   instance= new Singleton();            }            }         }           return singleton;       }   }  
(5)静态内部类单例模式
public class Singleton {     private Singleton(){    }    public static Singleton getInstance(){          return SingletonHolder.instance;      }      private static class SingletonHolder {          private static final Singleton instance = new Singleton();      }  } 
优点:第一次加载Singleton类时并不会初始化instance,只有第一次调用getInstance方法时虚拟机加载SingletonHolder 并初始化instance ,这样不仅能确保线程安全也能保Singleton类的唯一性,所以推荐使用静态内部类单例模式。
(6)枚举单例
public enum Singleton {       INSTANCE;       public void doSomeThing() {       }   }  
默认枚举实例的创建是线程安全的,并且在任何情况下都是单例,上述讲的几种单例模式实现中,有一种情况下他们会重新创建对象,那就是反序列化,将一个单例实例对象写到磁盘再读回来,从而获得了一个实例。反序列化操作提供了readResolve方法,这个方法可以让开发人员控制对象的反序列化。在上述的几个方法示例中如果要杜绝单例对象被反序列化是重新生成对象,就必须加入如下方法:
private Object readResolve() throws ObjectStreamException{    return singleton;}
枚举单例的优点就是简单,但是大部分应用开发很少用枚举,可读性并不是很高,不建议用。
(7)使用容器实现单例模式
public class SingletonManager {   private static Map<String, Object> objMap = new HashMap<String,Object>();  private Singleton() {   }  public static void registerService(String key, Objectinstance) {    if (!objMap.containsKey(key) ) {      objMap.put(key, instance) ;    }  }  public static ObjectgetService(String key) {    return objMap.get(key) ;  }}

用SingletonManager 将多种的单例类统一管理,在使用时根据key获取对象对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。

4. 单例模式的应用场景:

(1). Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~ 

(2). windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

(3). 网站的计数器,一般也是采用单例模式实现,否则难以同步。

(4). 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。

(5). Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。

(6). 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

(7). 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

(8). 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。


参考资料:
1. http://blog.csdn.net/itachi85/article/details/50510124;
2.《研磨设计模式》;
3.《设计模式之禅(第二版)》;

4. http://www.oodesign.com/singleton-pattern.html

5. http://blog.csdn.net/tanyujing/article/details/14160941

0 0
原创粉丝点击