顾名思义,单例模式就是一个类只有一个实例,而且这个实例易于被外界访问,从而方便对实例个数的控制并节约系统资源。如果在设计过程中希望某个类只有一个实例,那么这时候单例模式可以是一个比较好的选择。
所谓天无二日,人无二主。那么就以太阳为例好了,众所周知,我们每天看到的太阳都是同一个太阳。
现在来看看最简单的单例模式
package com.pu.singleton;
/**
*
* @author puhaitao
*
*/
public class Sun {
private static Sun sun;
private Sun(){
}
public static Sun getSun(){
if(sun==null){
sun=new Sun();
}
return sun;
}
}
package com.pu.singleton;
public class TestSun {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sun sun=Sun.getSun();
System.out.println(sun.hashCode());
Sun sun1=Sun.getSun();
System.out.println(sun1.hashCode());
B b=new B();
System.out.println(b.hashCode());
B b1=new B();
System.out.println(b1.hashCode());
}
}
运行输出结果如下
可见,单例模式的各个实例的hashcode都是一样的,而普通类B的各个实例都有自己的hashcode。
上边的Sun类,我们还可以这么写:
package com.pu.singleton;
/**
*
* @author puhaitao
*
*/
public class Sun {
private static Sun sun=new Sun();
private Sun(){
}
public static Sun getSun(){
return sun;
}
}
很明显,这种写法,类装载时候就进行实例化了,这种方式叫做饿汉式,而第一种则称为饱汉式。
但是上面懒汉式不是线程安全的,那么线程安全的单例模该改如何写呢,请看代码,这种方式俗称双重锁定。
package com.pu.singleton;
/**
*
* @author puhaitao
*
*/
public class Sun {
private static Sun sun;
private Sun(){
}
public static Sun getSun(){
if(sun==null){
synchronized(Sun.class){
if(sun==null){
sun=new Sun();
}
}
}
return sun;
}
}
有人总结出单例模式有七种写法,我就不一一实现了,最后来看一个以枚举来实现的单例模式,看起来很简洁。
package com.pu.singleton;
/**
*
* @author puhaitao
*
*/
public enum Sun {
SUN{
@Override
protected void someMethod() {
// TODO Auto-generated method stub
}};
protected abstract void someMethod();
}