首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

小弟我的设计模式学习笔记->单例模式(Singleton)

2013-10-17 
我的设计模式学习笔记------单例模式(Singleton)一、前言 有些时候,允许自由创建某个类的实例是没有意义,

我的设计模式学习笔记------>单例模式(Singleton)
一、前言

有些时候,允许自由创建某个类的实例是没有意义,还可能造成系统性能下降(因为创建对象所带来的系统开销问题)。例如整个Windows系统只有一个窗口管理器,只有一个回收站等。在Java EE应用中可能只需要一个数据库引擎访问点,Hibernate访问时只需要一个SessionFactory实例,如果在系统中为它们创建多个实例就没有太大的意义。

如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式就被称为单例模式。

对Spring框架而言,可以在配置Bean实例时指定scope="singleton"类配置单例模式。不仅如此,如果配置<bean .../>元素时没有指定scope属性,则该Bean实例默认是单例的行为方式。

Spring推荐将所有业务逻辑组件、DAO组件、数据源组件等配置成单例的行为方式,因为这些组件无须保存任何用户状态,故所有客户端都可以共享这些业务逻辑组件、DAO组件,因此推荐奖这些组件配置成单例的行为方式。

二、基本定义

在阎宏博士的《JAVA与模式》一书中开头是这样描述单例模式的:

  作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

单例模式有以下几个特点:

      单例类只能有一个实例。单例类必须自己创建自己的唯一实例。单例类必须给所有其他对象提供这一实例。
单例模式的模式结构:小弟我的设计模式学习笔记->单例模式(Singleton)

 单例模式可以说是最简单的设计模式了,它仅有一个角色Singleton。

         Singleton:单例。

三、单例模式的具体实现

1、饿汉式实现单例模式
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从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。但是失去了类的一些特性,没有延迟加载。

四、单例模式的优缺点1、优点提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。

2、缺点由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。
五、单例模式的使用场景系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式。

==================================================================================================

  作者:欧阳鹏  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址:http://blog.csdn.net/ouyang_peng

==================================================================================================


热点排行