zoukankan      html  css  js  c++  java
  • 设计模式---单例模式

    1)简介
    
    单例设计模式是一种创建设计模式,单例类只能有一个实例存在。
    核心步骤:私有构造,自建实例,提供访问方法
    
    2)实现代码
    a.饿汉式
    public class Singleton{
        //自建实例,注意是静态变量以确保唯一,私有
        private static Singleton instance = new Singleton();
        //私有构造,防止其他地方创建对象
        private Singleton(){}
        //提供访问单例的方法
        public Singleton getInstance(){
            return instance;
        }
    }
    饿汉式优点是一加载类就创建实例,避免了线程安全问题,缺点是单例实例可能很久不使用,一直存在于内存有些浪费资源(不过现在内存貌似比较廉价,可以忽略这点吧)
    
    b.懒汉式
    public class Singleton{
        //声明变量,暂时不创建实例
        private static Singleton instance;
        //私有构造,防止其他地方创建对象
        private Singleton(){}
        //提供访问单例的方法
        public Singleton getInstance(){
            //判断是否为空,根据结果创建实例
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }
    这种懒汉式虽然节约了资源,但是存在线程安全问题:即一个线程判断为空后失去CPU执行权限,另一个线程又判断为空,两个线程最终都创建了一个实例。
    
    懒汉式同步方法模式:
    public class Singleton{
        //声明变量,暂时不创建实例
        private static Singleton instance;
        //私有构造,防止其他地方创建对象
        private Singleton(){}
        //提供访问单例的方法
        public synchronized Singleton getInstance(){
            //判断是否为空,根据结果创建实例
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }
    这种懒汉式当getInstance方法调用的次数少时可以,调用多的时候因为对整个方法都进行加锁,会影响性能。
    
    懒汉式双检锁模式(DCL double-checked locking):
    public class Singleton{
        //声明变量,暂时不创建实例
        private static Singleton instance;
        //私有构造,防止其他地方创建对象
        private Singleton(){}
        //提供访问单例的方法
        public Singleton getInstance(){
            //判断是否为空,根据结果创建实例
            if(instance == null){
                synchronized(Singleton.class){
                    if(instance == null){
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    这种懒汉式即线程安全,又不会因为同步创建对象影响性能
    但是,如果单例对象需要进行序列化和反序列化操作,单例模式会被破坏掉,原因稍后说明
    
    c.登记模式/静态内部类
    public class Singleton{
        //静态内部类持有实例
        private static class SingletonHolder{
            private static final Singleton INSTANCE = new Singleton();
        }
        //私有构造
        private Singleton(){}
        public static Singleton getInstance(){
            return SingletonHolder.INSTANCE;
        }
    }
    静态内部类模式利用内部类加载时创建单例实例,避免了线程安全问题,且类加载是在主动调用的时候加载,因此又具备lazy初始化的功能,另外单例实例是静态内部类的属性,反序列化时虽然通过反射创建了单例类的实例,但是通过getInstance获取实例的时候依然是原来的实例。
    
    d、枚举
    public enum Singleton{
        INSTANCE;
    }
    
    3)返序列化破坏单例的说明
    序列化与反序列化代码:
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //Write Obj to file
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test"));
        oos.writeObject(Singleton.getSingleton());
        //Read Obj from file
        File file = new File("test");
        ObjectInputStream ois =  new ObjectInputStream(new FileInputStream(file));
        Singleton newInstance = (Singleton) ois.readObject();
        //判断是否是同一个对象
        System.out.println(newInstance == Singleton.getSingleton());
    }
    输出结果为false
    ObjectInputStream类的readObject 读取对象时返回的对象是调用 readOrdinaryObject 返回的对象,
    readOrdinaryObject 方法有下面一段代码,返回的是其中的obj
    Object obj;
    try {
        obj = desc.isInstantiable() ? desc.newInstance() : null;
    } catch (Exception ex) {
        throw (IOException) new InvalidClassException(
            desc.forClass().getName(),
            "unable to create instance").initCause(ex);
    }
    isInstantiable 方法为校验是否可以序列化,如果可以返回true,我们需要序列化,肯定返回true
    故返回的对象实际为desc.newInstance()返回的对象,而desc为Class对象,显然最终返回的是通过反射新建的一个实例,已经不是原来的实例了。
  • 相关阅读:
    VB Treeview控件 介绍与使用
    基于V4L2的视频驱动开发
    Jlinkv8 灯不亮重新烧写固件的办法
    使用JLink间接烧写S3C2410、S3C2440开发板Nor、Nand Flash的方法
    linux 开机自动执行脚本或者一些指定的程序
    FrameBuffer编程二(简单程序下)
    c语言内存分配函数
    FrameBuffer编程二(简单的程序上)
    FrameBuffer编程一(数据结构)
    mmap函数介绍
  • 原文地址:https://www.cnblogs.com/ShouWangYiXin/p/12143164.html
Copyright © 2011-2022 走看看