Singleton通常被用来代表那些本质上唯一的系统组件,在JDK1.5之前,实现Singleton有两种方法。这两种方法都要把构造器保持为私有的,并导出公有的静态成员,以便允许客户端能够访问该类的唯一实现。
第一种方式:1.构造器私有,2,有一个公共的静态成员,并且是final的。
public class TestSingleton { private TestSingleton(){ //在此将构造函数设置为private,防止该类在外部被实例化 } public static final TestSingleton Instance = new TestSingleton(); public void test(){ System.out.println("Test..."); } }
ps:构造方法私有化的作用:外面调用只能调用类A的静态函数A_Func,而不能A a = new A();私有构造函数只能在函数内部调用,外部不能实例化,所以私有构造函数可以防止该类在外部被实例化。
不过上述方式是不能保证绝对的只有一个实例,通过反射机制可以突破这一点,所以该方法不推荐。传说中的饿汉式的单例模式。
第二种方式:1,构造器私有,2,有一个私有的静态长远,但是有一个公共的静态工厂方法
public class TestSingleton1 { private static final TestSingleton1 INSTANCE = new TestSingleton1(); private TestSingleton1(){} public static TestSingleton1 getInstance(){ return INSTANCE; } public void test(){ System.out.println("Test..."); } }
这就是传说中的懒汉式的单例模式,一般情况下,为了防止多线程的时候创建多个实例,都会加上synchronized 关键字。
对于静态方法getInstance()方法的所有调用,都会返回同一个对象的应用。这种写法的好处是很清楚地表明了该类是一个Singleton,但是这种写法有另一个好处是,可以添加其他的静态工厂方法返回另一个新的实例,这样就可以将该类变为非Signleton。
为了使利用上述方法实现Singleton类变成是可序列化的,仅仅在声明时加上“implements Serializable”是不够的。为了保证singleton必须声明所有实例域都是瞬时的(transient),并且还需要提供一个readResolve方法。否则每次反序列化都会创建一个实例。
从JDK1.5开始,实现Singleton还有第三种方法,只需编写一个包含单个元素的枚举类型。推荐的写法:
public enum Singleton { INSTANCE; public void test(){ System.out.println("test..."); } }
单元素的枚举类型已经成为实现Singleton的最佳方法。