我的设计模式学习笔记------>单例模式(Singleton)
一、前言
有些时候,允许自由创建某个类的实例是没有意义,还可能造成系统性能下降(因为创建对象所带来的系统开销问题)。例如整个Windows系统只有一个窗口管理器,只有一个回收站等。在Java EE应用中可能只需要一个数据库引擎访问点,Hibernate访问时只需要一个SessionFactory实例,如果在系统中为它们创建多个实例就没有太大的意义。
如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式就被称为单例模式。
对Spring框架而言,可以在配置Bean实例时指定scope="singleton"类配置单例模式。不仅如此,如果配置<bean .../>元素时没有指定scope属性,则该Bean实例默认是单例的行为方式。
Spring推荐将所有业务逻辑组件、DAO组件、数据源组件等配置成单例的行为方式,因为这些组件无须保存任何用户状态,故所有客户端都可以共享这些业务逻辑组件、DAO组件,因此推荐奖这些组件配置成单例的行为方式。
二、基本定义在阎宏博士的《JAVA与模式》一书中开头是这样描述单例模式的:
作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
单例模式有以下几个特点:
单例模式可以说是最简单的设计模式了,它仅有一个角色Singleton。
Singleton:单例。
public class DoubleCheckLockSingleton {private DoubleCheckLockSingleton() {}/** * 关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存, * 所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量 */private static volatile DoubleCheckLockSingleton instance = null;public static DoubleCheckLockSingleton getInstance() {//先检查实例是否存在,如果不存在才进入下面的同步块if (instance == null) { //同步块,线程安全的创建实例synchronized (DoubleCheckLockSingleton.class) { //再次检查实例是否存在,如果不存在才真正的创建实例if (instance == null) {instance = new DoubleCheckLockSingleton();}}}return instance;}}
这种实现方式既可以实现线程安全地创建实例,而又不会对性能造成太大的影响。它只是第一次创建实例的时候同步,以后就不需要同步了,从而加快了运行速度。
由于volatile关键字可能会屏蔽掉虚拟机中一些必要的代码优化,所以运行效率并不是很高。因此一般建议,没有特别的需要,不要使用。也就是说,虽然可以使用“双重检查加锁”机制来实现线程安全的单例,但并不建议大量采用,可以根据情况来选用。
(更多关于双重检查锁定单例可以参考:我的Java开发学习之旅------>Java双重检查锁定及单例模式详解)
根据上面的分析,常见的两种单例实现方式都存在小小的缺陷,那么有没有一种方案,既能实现延迟加载,又能实现线程安全呢?
4、静态内部类实现单例模式public enum EmunSingleton {/** * 定义一个枚举的元素,它就代表了EmunSingleton的一个实例。 */INSTANCE;}使用枚举来实现单实例控制会更加简洁,而且无偿地提供了序列化机制,并由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。但是失去了类的一些特性,没有延迟加载。
==================================================================================================
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/ouyang_peng
==================================================================================================