设计模式之单例模式

来源:互联网 发布:软件接口测试 编辑:程序博客网 时间:2024/04/27 20:51

一、单例模式
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(); }
0 0