一、单例模式
1.单例模式定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点,该类不可子类化。
2.单例模式的UML
3.单例模式的示例
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
*
* 饱汉式单例模式
* @author shier
*
*/
@SuppressWarnings("serial")
public class FullManSinglton implements Serializable{
//饱汉模式,声明时就创建实例对象
public static final FullManSinglton instance = new FullManSinglton();
/**单类模式的构造方法必须为private,以避免通过构造方法创建对象实例,
*并且必须显示声明构造方法,以防止使用默认构造方法
*虽然构造方式的访问修饰符为private,即除了自身以外其他任何类都无法调用,但是通过反射机制的
*AccessibleObject.setAccessible(true)方法可以访问私有方法和属性
*/
private FullManSinglton(){
if(null != instance)
throw new RunTimeException("不可以使用反射访问单例对象");
}
public static FullManSinglton getInstance(){
return instance;
}
public String getString(){
String s ="i am a full man";
return s;
}
/**
* 实现单例模式的类变成可序列化的时候,不仅implements Serializable
* 必须声明所有的实例域都是瞬时的(transient)
* 重写readResolve方法,防止反序列化时,获取对象不是唯一
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return instance;
}
}
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* 饿汉式单例模式,延迟化加载,线程不安全的
* @author shier
*
*/
@SuppressWarnings("serial")
public class HungryManSinglton implements Serializable{
//饿汉模式,声明时不创建实例对象
public static HungryManSinglton instance;
/**单类模式的构造方法必须为private,以避免通过构造方法创建对象实例,
*并且必须显示声明构造方法,以防止使用默认构造方法
*虽然构造方式的访问修饰符为private,即除了自身以外其他任何类都无法调用,但是通过反射机制的
*AccessibleObject.setAccessible(true)方法可以访问私有方法和属性
*/
private HungryManSinglton(){
if(null != instance)
throw new RunTimeException("不可以使用反射访问单例对象");
}
//单类模式必须对外提供获取实例对象的方法,延迟初始化的单类模式必须使用synchronized同步关键字,否则多线程情况下很容易产生多个实例对象
public static synchronized HungryManSinglton getInstance(){
//延迟初始化,只有当第一次使用时才创建对象实例
if(instance==null)
instance = new HungryManSinglton();
return instance;
}
public String getString(){
String s ="i am a hungry man";
return s;
}
/**
* 实现单例模式的类变成可序列化的时候,不仅implements Serializable
* 必须声明所有的实例域都是瞬时的(transient)
* 重写readResolve方法,防止反序列化时,获取对象不是唯一
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return instance;
}
}
import java.io.ObjectStreamException;
/**
* 双重锁定单例模式
* @author shier
*
*/
public class DoubleLockSinglton {
public static DoubleLockSinglton instance;
/**单类模式的构造方法必须为private,以避免通过构造方法创建对象实例,
*并且必须显示声明构造方法,以防止使用默认构造方法
*虽然构造方式的访问修饰符为private,即除了自身以外其他任何类都无法调用,但是通过反射机制的
*AccessibleObject.setAccessible(true)方法可以访问私有方法和属性
*/
private DoubleLockSinglton(){
if(null != instance)
throw new RunTimeException("不可以使用反射访问单例对象");
}
public static DoubleLockSinglton getInstance(){
//先判断实例是否存在,不存在在加锁处理,这样提高运行的效率
if(instance == null){
synchronized (DoubleLockSinglton.class) {
if(instance == null)
instance = new DoubleLockSinglton();
}
}
return instance;
}
public String getString(){
String s ="i am a double lock man";
return s;
}
/**
* 实现单例模式的类变成可序列化的时候,不仅implements Serializable
* 必须声明所有的实例域都是瞬时的(transient)
* 重写readResolve方法,防止反序列化时,获取对象不是唯一
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return instance;
}
}
import java.io.ObjectStreamException;
/**
* 静态内部类单例模式
* @author shier
*
*/
public class StaticInwardSinglton {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
*/
public static class singltonHandler{
//由于是静态的域,因此只会被虚拟机在装载类的时候初始化一次,静态初始化器,由JVM来保证线程安全
public static StaticInwardSinglton instance = new StaticInwardSinglton();
}
/**单类模式的构造方法必须为private,以避免通过构造方法创建对象实例,
*并且必须显示声明构造方法,以防止使用默认构造方法
*虽然构造方式的访问修饰符为private,即除了自身以外其他任何类都无法调用,但是通过反射机制的
*AccessibleObject.setAccessible(true)方法可以访问私有方法和属性
*/
private StaticInwardSinglton(){
if(null != instance)
throw new RunTimeException("不可以使用反射访问单例对象");
}
public static StaticInwardSinglton getInstance(){
return singltonHandler.instance;
}
public String getString(){
String s ="i am a static inward man";
return s;
}
/**
* 实现单例模式的类变成可序列化的时候,不仅implements Serializable
* 必须声明所有的实例域都是瞬时的(transient)
* 重写readResolve方法,防止反序列化时,获取对象不是唯一
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return singltonHandler.instance;
}
}
/**
* 枚举单例模式
* @author shier
* effective java中推荐,最安全的单例模式
*/
public enum SingltonEnum {
INSTANCE{
@Override
public void doSomething() {
System.out.println("i am a enum man");
}};
public abstract void doSomething();
}