注册式单例模式简单记录

x33g5p2x  于11个月前 转载在 其他  
字(1.6k)|赞(0)|评价(0)|浏览(69)

枚举式单例模式

//枚举式单例模式
public enum EnumSingleton
{
    INSTANCE;
    //等价于==>饿汉式单例模式
// static 
// {
// INSTANCE=new EnumSingleton("INSATNCE",0); 
// }
    
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance(){
        //返回当前类的单例对象
        return INSTANCE;
    };
}

测试:

//枚举式_单例_测试类
public class enum_test
{
    public static void main(String[] args)
    {
        try
        {
            //检验序列化是否会破坏单例模式
            EnumSingleton singleton=null;
            singleton=EnumSingleton.getInstance();
            singleton.setData(new Object());

            //刷入硬盘
            FileOutputStream fos=new FileOutputStream("EnumSignleton.obj");
            ObjectOutputStream oos=new ObjectOutputStream(fos);
            oos.writeObject(singleton);
            oos.flush();
            oos.close();

            //读取出来
            FileInputStream fis=new FileInputStream("EnumSignleton.obj");
            ObjectInputStream ois=new ObjectInputStream(fis);
            EnumSingleton o = (EnumSingleton)ois.readObject();
            ois.close();

            System.out.println(singleton.getData());
            System.out.println(o.getData());
            System.out.println(singleton.getData()==o.getData());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }
}

枚举式单例模式特点:

  • 通过研究底层源码得知,序列化并不会在readObject方法中new一个枚举实例对象,而是通过类名和类对象找到一个唯一的枚举对象,因此枚举对象在序列化过程中不会被类加载器加载多次
  • 并且通过反射也无法破坏枚举式单例模式,因此在newInstance方法中做了强制性判断,如果修饰符是枚举类型,则直接抛出异常

容器式单例模式

//容器式单例
public class containerSingleton
{
    //构造器私有化
    private containerSingleton(){}
    //ioc容器 并发容器
    private  static Map<String,Object> ioc=new ConcurrentHashMap<>();
    public static Object getBean(String className)
    {
      synchronized (ioc)
      {
          if(!ioc.containsKey(className))
          {
              Object obj=null;
              try
              {
                  obj=Class.forName(className).newInstance();
                  ioc.put(className,obj);
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
             return obj;   
          }
          else
              return ioc.get(className);
      }
    }
}

相关文章