一、单态模式的定义
Singleton模式要求一个类有且仅有一个实例,并且提供一个全局的访问点。

二、使用Singleton注意事项:
有时在某些情况下,使用Singleton并不能达到Singleton的目的,如有多个Singleton对象同时被不同的类装入器装载;在EJB(Enterprise Java Beans)这样的分布式系统中使用也要注意这种情况,因为EJB是跨服务器,跨JVM的
(我们以SUN公司的宠物店源码(Pet Store 1.3.1)的ServiceLocator为例稍微分析一下:
在Pet Store中ServiceLocator有两种,一个是EJB目录下;一个是WEB目录下,我们检查这两个ServiceLocator会发现内容差不多,都是提供EJB的查询定位服务,可是为什么要分开呢?仔细研究对这两种ServiceLocator才发现区别:在WEB中的ServiceLocator的采取Singleton模式,ServiceLocator属于资源定位,理所当然应该使用Singleton模式。但是在EJB中,Singleton模式已经失去作用,所以ServiceLocator才分成两种,一种面向WEB服务的,一种是面向EJB服务的。 )

三、使用单态模式的优点:
1.控制资源的使用,通过线程同步来控制资源的并发访问;
2.控制实例产生的数量,节省内存,有利于垃圾回收。
3.作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。
比 如,数据库连接池的设计一般采用单例模式,数据库连接是一种数据库资源。软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的。当然,使用数据库连接池还有很多其它的好处,可以屏蔽不同数据数据库之间的差异,实现系统对数据库的低度耦合,也可 以被多个系统同时使用,具有高可复用性,还能方便对数据库连接的管理等等。数据库连接池属于重量级资源,一个应用中只需要保留一份即可,既节省了资源又方便管理。所以数据库连接池采用单例模式进行设计会是一个非常好的选择。



四、生活中的例子:
1.每台计算机可以有若干个打印机,如果每一个进程或者线程都独立地使用打印机资源的话,那么我们打印出来的结果就有可能既包含这个打印任务的一部分,又包含另外一个打印任务的一部分。所以,大多数的操作系统最终为打印任务设计了一个单例模式的假脱机服务Printer Spooler,所有的打印任务都需要通过假脱机服务进行。
2.在我们日常使用的在Windows中也有不少单例模式设计的组件,象常用的文件管理器。由于Windows操作系统是一个典型的多进程多线程系统,那么在创建或者删除某个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象。采用单例模式设计的文件管理器就可以完美的解决这个问题,所有的文件操作都必须通过唯一的实例进行,这样就不会产生混乱的现象。



五、2种实现:
实现原理:首先必须将类的构造方法的访问权限设为private,这样就不能用new操作符在类的外部产生该类的对象实例了。其次在类的内部产生一个静态的对象,再产生该类的静态方法返回内部创建的对象实例以便外部来访问这个唯一的对象实例。(外部要访问唯一对象,只有内部来创建,需定义一个方法来返回对象,而且必须是静态的,静态的方法只能访问静态变量,所以定义的对象变量也必须是静态的。)

1.第一种形式:

Java代码

1.public classSingleton {

2.  private Singleton(){}

3.  //注意这个实例是private的, 只供内部调用

4.  private staticSingleton instance = new Singleton();

5.  //这里提供了一个供外部访问本class的静态方法,可以直接访问  

6.  public staticSingleton getInstance() {

7.    return instance;   

8.   }

9.}

public class Singleton {

  private Singleton(){}

  //注意这个实例是private的, 只供内部调用

  private static Singletoninstance = new Singleton();

  //这里提供了一个供外部访问本class的静态方法,可以直接访问  

  public static SingletongetInstance() {

    return instance;   

   }

}


2.第二种形式:

Java代码

1.public classSingleton {

2.  private staticSingleton instance = null;

3.  public staticsynchronized Singleton getInstance() {

4.  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次    

5.  //使用时生成实例,提高了效率!

6.  if (instance==null)

7.    instance=new Singleton();

8.  return instance;   }

9.}

public class Singleton {

  private static Singletoninstance = null;

  public staticsynchronized Singleton getInstance() {

  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次    

  //使用时生成实例,提高了效率!

  if (instance==null)

    instance=new Singleton();

  return instance;   }

}



使用Singleton.getInstance()可以访问单态类。

第二种形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。

注意到lazy initialization形式中的synchronized(线程同步),这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。在一个多线程的程序中,如果同步的消耗是很大的,很容易造成瓶颈。

一般认为第一种形式要更加安全些。