第3条 用私有构造器或者枚举类型强化Singleton属性

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

相关文章
相关标签/搜索