2024-10-22
基本概念
Singleton 是一种创立性模型,它用来确保只发生一个实例,并供给一个访问它的大局访问点.对一些类来说,确保只要一个实例是很重要的,比方有的时候,数据库衔接或 Socket 衔接要遭到一定的约束,必须保持同一时间只能有一个衔接的存在.再举个比如,调集中的 set 中不能包含重复的元素,添加到set里的目标必须是仅有的,假如重复的值添加到 set,它只承受一个实例.JDK中正式运用了Singleton形式来完成 set 的这一特性,我们能够检查java.util.Collections里的内部静态类SingletonSet的原代码.其实Singleton是简单但也是应用广泛的形式之一,在 JDK 中随处可见.
简单分析
为了完成 Singleton 形式,咱们需要的是一个静态的变量,能够在不创立目标的情况下回忆是否现已发生过实例了.静态变量或静态方法都能够在不发生详细实例的情况下直接调用,这样的变量或方法不会由于类的实例化而有所改动.在图1的结构中能够看到,uniqueInstance 便是这个独立的静态变量,它能够回忆目标是否现已实例化了,在静态方法 Instance 中对这个变量进行判别,若没有实例化过就发生一个新的目标,假如现已实例化了则不再发生新的目标,仍然返回曾经发生的实例.
详细施行
完成 Singleton 形式的方法通常有三种.
一. 用静态方法完成 Singleton 这种方法是使用静态方法来监督实例的创立.为了避免创立一个以上的实例,咱们好把结构器声明为 private.
这样能够避免客户程序员经过除由咱们供给的方法之外的恣意方法来创立一个实例,假如不把结构器声明为private,编译器就会自作聪明的自动同步一个默认的friendly结构器.这种完成方法是常见的,也便是图1中结构的规范完成.
singletonTest运行结果是:
Creating one instance
Creating two instance
Only one instance allowed
能够看出,第一个实例顺利创立,第二个实例创立实抛出了咱们自定义的异常.
三. 用注册器机制来创立 Singleton 首先用调集中的Hashtable 和Enumeration来完成addItem(Object key, Object value),getItem(Object key), ,removeItem(Object key)等方法完成一个办理器,将key和value逐个关联起来,客户程序员创立实例前首先用addItem方法进行注册,再用getItem方法获取实例.Hashtable中的key是仅有的,从而确保创立的实例是仅有的,详细完成限于篇幅不再细说,在Prototype模型的应用一文中我将会给出一个完成注册器的代码.用注册器机制来创立 Singleton形式的优点是易于办理,能够同时控制多个不同类型的Singleton 实例.
小结
Singleton形式能够方便的进行扩充,发生指定数目的实例.
在The Design Patterns Java Companion 一书中曾提到过用静态类的方法来完成 Singleton形式,并指出java.lang.Math便是一个比如,这儿我并不表明赞同,由于Math并不是一个真正的目标,咱们仅仅直接调用Math类所包装的静态方法而已,根本就没有创立实例的过程,又从何说起只发生一个实例呢?这个问题我曾到Javaranch的论坛上发过帖子,所有回帖的人也都是对这一观点持否定态度.
在多线程的程序中,singleton可能会变的不可靠,可能会出现多个实例,解决的方法很简单,加个同步修饰符: public static synchronized Singleton getInstance(). 这样就确保了线程的安全性.
后要说的是我们可能会看见一些其他完成Singleton形式的方法,由于形式在详细的应用时是灵活的,不是一成不变的,并没有一个固定的做法,但大都是上面几种方法的变形.但也要注意单例模式可能会带来一些问题,如测试困难、可能会隐藏不良的设计等,在使用时需要根据具体情况进行权衡。