Singleton-------唯一:
以前是商标满天飞,相同的商标难免造成侵权,直从有商标保护法后,就保证了不会再产生第家企业使用相同的商标;
说到Singleton,就不能不提全局变量。过去我们反对全局变量,为什么呢?全局变量一般存在三个问题:
<!--[if !supportLists]-->1. 命名冲突,也叫名字污染<!--[endif]-->
<!--[if !supportLists]-->2. 初始化顺序依赖问题。<!--[endif]-->
<!--[if !supportLists]-->3. 远程代码耦合问题。<!--[endif]-->
对于第一个问题,其实解决很简单,通过命名规范可以有效解决。另外,借助语言机制也容易解决,例如C++的namespace, class或struct的静态数据成员。Java和C#根本不允许全局变量,并且引入包机制,都可以缓解甚至消除这一影响,至少,Singleton对该问题的解决力度并不超过这些语言提供的内建机制。
初始化顺序依赖问题是一个相当微妙的问题。借助于Singleton, 我们可以强制某些对象按需创建,避免初始化顺序依赖导致的问题。然而,初始化顺序是一个雷区,我们必须小心翼翼地绕过去,但首先不应该通过实现技术来规避问题,而应该调整设计,让初始化顺序问题根本不出现才是上策。第二,某些情况下,我们确实需要规避初始化顺序问题,我们也需要清醒地认识到该实现手段影响到的代码范围,受其影响的部分越单一越好。
远程代码耦合,这是我们反对全局变量的核心问题。任何长距离的耦合都将导致代码的可读性下降,进而可能影响代码结构,导致结构僵化,无力应对因需求变化导致的结构调整。很遗憾,Singleton并不能对这个问题有任何帮助。当我们回避全局变量的时候,事实上,我们也规避了上述的三个问题。可是,如果我们不能审慎地使用Singleton就会重新落入全局变量的核心陷阱中去。
名称
|
Singleton
|
结构
|
|
意图
|
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
|
适用性
|
-
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
-
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
|
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。
还有, singleton能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛中的帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能synchronize的安全自动加1,如果你要把这个数字永久保存到数据库,你可以在不修改单态接口的情况下方便的做到。
另外方面,Singleton也能够被无状态化。提供工具性质的功能,
Singleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbage collection)。
我们常常看到工厂模式中类装入器(class loader)中也用Singleton模式实现的,因为被装入的类实际也属于资源。
如何使用?
一般Singleton模式通常有几种形式:
public class Singleton { private Singleton(){} //在自己内部定义自己一个实例,是不是很奇怪? //注意这是private 只供内部调用 private static Singleton instance = new Singleton(); //这里提供了一个供外部访问本class的静态方法,可以直接访问 public static Singleton getInstance() { return instance; } } |
第二种形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次 //使用时生成实例,提高了效率! if (instance==null) instance=new Singleton(); return instance; } } |
使用Singleton.getInstance()可以访问单态类。
上面第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。
注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴趣者进一步研究。
一般认为第一种形式要更加安全些。