1.什么是Singleton模式
Singleton模式,是为了实现在一个应用程序中,某一个类只能有一个实例,也就是说只能产生一个对象。
Singleton是一种创建型模式,这意味着,如果某个类采用了Singleton模式,则在这个类被创建后,它将只可能产生一个实例供外部访问,并且会提供一个全局的访问点。
一眼看去,Singleton似乎有些像全局对象。但是实际上,全局对象和Singleton模式有本质的区别,这是因为大量使用全局对象会使得程序质量降低,而且有些编程语言根本就不支持全局变量。最重要的是传统的全局对象并不能阻止人们将一个类实例化多次。而Singleton模式则通过从根本上控制类的创建,将"保证一个类有且只有一个实例"这个任务交给了类本身。这一点是全局对象方法与Singleton模式的根本区别。
2.如何实现Singleton模式
与其他所有的模式一样,Singleton模式只是一种理念,而具体的实现则有各种不同的方法。在这里,我知道的主要有下面四种方法:
(1)使用静态方法来实现实例的创建
这里要注意使用一个private的构造方法。如果不把构造器声明为private,java的编译器会自动同步一个默认的friendly构造器.
代码:
public class Singleton {
/*
* private constructor to make sure nobody can create an
* object using it.
*/
private Singleton(){};
private static Singleton singleton;
/*
* Global method for instancing of the class.
*/
//make sure you use a static method
public static synchronized Singleton getInstance() {
if (singleton == null)
singleton = new Singleton();
return singleton;
}
//other method
}
(2)纯静态对象实现
产生一个纯静态的对象,然后给出一个全局的访问点供其他的对象调用
一般认为这种方式更安全一些。Jdon的板桥里人先生也是这种观点。
代码:
public class Singleton {
private Singleton(){}
//use private and static keywords
private static Singleton instance = new Singleton();
//Global access
public static synchronized Singleton getInstance() {
return instance;
}
}
(3)设置一个静态变量作为标志位
这种方法的原理类似于第一种方法,只不过并不是判断singleton的实例是不是存在,而是另外设置一个标志位来判断。
代码:
public class Singleton {
static boolean instance_flag = false; // true if a instance exist
public Singleton() {
if (instance_flag)
{
//define Exception to throw
}
else{
instance_flag = true; // false if no instance exist
}
}
//other method
}
(4)自定义Singleton生成器
自己设计一个Singleton生成器,在一定程度上可以理解为工场模式的扩展。在这种方式下,可以转化Singleton的特点,甚至通过一定方式改变生成的Instance的数目(好像这样就不应该再叫Singleton,我见过有一种说法叫多例)。主要实现方法可以通过Hashtable或者相应的数据结构然后设置标志位和长度。
有兴趣的可以仔细查一下这方面的资料,在多核或多CPU的情况下,使用这种方式会更好一些。
3.什么时候使用Singleton模式
很多时候我们都会需要Singleton模式,最常见的比如我们希望整个应用程序中只有一个连接池实例等。但是,这种模式虽然简单,想用好却很不容易,需要考虑JVM,内存,线程,分布式等等情况。
模式本来就是一个有很大不确定性因素的东西,因此,具体什么时候使用Singleton模式,需要非常小心,同时,也没有一个完整的评价标准来确定倒底什么时候使用Singleton模式。
我个人的意见是,如果是一个容器内的应用,那么最好不要使用单例,如果需要使用,那么一定要注意分布式和多线程的问题。
另外,关于lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了,上面除了第二种方法以外,应该都属于lazy initialization。这部分的知识我理解也不够深入,不过一定要使用synchronized,如果没有使用synchronized,那么使用getInstance()是有可能得到多个Singleton实例;同时,synchronized也有可能造成浪费过多的CPU资源在一些不必要的同步上。
4.Singleton is evil or not?
很多人认为Singleton is evil。从设计上的角度来考虑,Singleton模式的引入会给程序带来一些不好的影响:
(1)结合了静态方法,由于静态方法一般由类定义,而不是接口,导致系统中其他程序过分依赖该类本身(对该类的引用被硬编码到其他类中),增加了系统的耦合度;
(2)由于静态方法和变量没有“继承”的概念,使该模式不利于扩展。
(3)由于Singleton的创建完全在本类中完成,对外界封闭,每个不同的singleton必须拥有完全独立的初始化过程,需要独立处理自己的配置。在一个大的系统中,越来越多的singleton导致系统越来越难维护。
在这里,没法确定谁对谁错,在参考文档中有相关文档,可以仔细去仔细读一读。
http://hi.baidu.com/mooncity/blog/item/68dad7888da00297a5c27226.html