Singleton一般被用来表明那些本质上惟一的系统组件,在JDK1.5以前,实现Singleton有两种方法。这两种方法都要把构造器保持为私有的,并导出公有的静态成员,以便容许客户端可以访问该类的惟一实现。java
第一种方式:1.构造器私有,2,有一个公共的静态成员,而且是final的。多线程
public class Singleton { private Singleton(){ //在此将构造函数设置为private,防止该类在外部被实例化 } public static final Singleton Instance = new Singleton(); public void test(){ System.out.println("Test..."); } }
构造方法私有化的做用:外面调用只能调用类的静态函数,而不能new去建立对象;私有构造函数只能在函数内部调用,外部不能实例化,因此私有构造函数能够防止该类在外部被实例化。不过享有特v权的客户端能够借助AccessibleObject.setAccessible()方法,经过反射机制调用私有构造器。若是须要抵御这种攻击,能够修改构造器,让他在被要求建立的第二个实例时候抛出异常。 函数
第二种方式:1,构造器私有,2,有一个私有的静态成员,可是有一个公共的静态工厂方法 spa
public class Singleton1 { private static final Singleton1 INSTANCE = new Singleton1(); private Singleton1(){} public static Singleton1 getInstance(){ return INSTANCE; } public void test(){ System.out.println("Test..."); } }
这就是传说中的懒汉式的单例模式,通常状况下,为了防止多线程的时候建立多个实例,都会加上synchronized 关键字。线程
对于静态方法getInstance()方法的全部调用,都会返回同一个对象的应用。这种写法的好处是很清楚地代表了该类是一个Singleton,可是这种写法有另外一个好处是,能够添加其余的静态工厂方法返回另外一个新的实例,这样就能够将该类变为非Signleton。为了使利用上述方法实现Singleton类变成是可序列化的,仅仅在声明时加上“implements Serializable”是不够的。为了维护并保证Singleton,必须声明全部实例都是瞬时transient的,并提供 一个readResolve方法。不然每次反序列化一个序列化的实例时,都会建立一个新的实例。即会致使一个假冒的对象。为了防止这种状况,须要在单例类中增长readResolve方法。延伸以下:code
public class Singleton implements Serializable { public static final Singleton INSTANCE = new Singleton(); private Singleton() { } private Object readResolve() { // Return the one true Elvis and let the garbage collector // take care of the Elvis impersonator. return INSTANCE; } }
实现Singleton还有第三种方法,从JDK1.5开始,只需编写一个包含单个元素的枚举类型。推荐的写法:对象
public enum Singleton3 { INSTANCE; public void test(){ System.out.println("test..."); } }
这种方法在功能上与公有域接近,可是它更简洁。虽然这种方法尚未普遍采用,可是单元素的枚举类型已经成为实现Singleton的最佳方法。get