单例的几种常见写法

作者: 小追兵 | 来源:发表于2015-12-14 11:28 被阅读6923次

    小追兵专栏

    单例设计模式

    第一种:饿汉式

    public class Singleton { 
        //实例化该单例对象。 
        private  static Singleton singleton=new Singleton(); 
        //私有化构造方法,使不能在别的类中new对象 
        private Singleton() {  
        }  
        //对外提供的一个获取该实例的方法
        public static Singleton getInstance() {  
           return singleton;  
        }  
    } 
    

    常见饿汉式就这种写法,不存在多线程同步等问题。可是存在一个问题,在类被加载的时候,就初始化了对象。即便我们还没想要用这个对象。下面 第三种 我们解决这个问题。

    第二种:懒汉式

    public class Singleton {  
        //volatile关键字,解决多处理器共享变量问题,防止编译器对代码进行优化,这个关键词的解释较为复杂,可以自行百度
        private volatile static Singleton singleton;  
      
        //私有化构造方法,不让new出其他对象。
        private Singleton() {  
        }  
      
        //暴露的获取这个单例对象的方法
        public static Singleton getInstance() {  
            
            //判断是否被实例化
            if (null == singleton) {  
                //同步锁,放在判断空的里面,是为了解决性能问题,这样只有在new的时候走一次同步锁,不用每次获取实例的时候走到这里。
                synchronized (Singleton.class) {  
                    //双重判空,这个必须要有,因为假设第一个线程进入了第一个判空之后,离开了并保存现场,没来得及创建对象,
                    //这时第二个线程进入了,顺利的实例化了对象离开了。此时前面离开的线程回来后,又创建了一个对象;
                    //这样就有多个对象存在。
                    if (null == singleton)  
                        singleton = new Singleton();  
                }  
            }  
            return singleton;  
        }  
    }  
    

    第三种:饿汉式升级版

    public class Singleton {  
         
        private Singleton() {  
        }  
        public static Singleton getInstance() {  
           return SingletonHolder.SINGLETON;  
        }  
    
        //静态内部类,解决了我们只有在调用getInstance方法后,才去创建这个单例实例的需求。不会因为加载这个类就创建实例,解决第一种方法的缺点。
        private static class SingletonHolder{  
            private  static Singleton SINGLETON=new Singleton();  
        }  
          
    }  
    

    第四种:枚举式

    大神为我们提供了一种不太好理解的方法,并且推荐使用。如下。

    public enum Singleton {  
        INSTANCE;  
      
        private Singleton() {  
        }  
      
        public String[] getName() {  
            final String[] names = new String[3];  
            names[0] = "小白";  
            names[1] = "小彩";  
            names[2] = "小丽";  
            return names;  
        }  
      
    } 
     
    

    在activity中这样调用:

    Log.e("猜猜我喜欢谁:",Singleton.INSTANCE.getName()[2]);
    

    注:

    • 我们使用单例,不一定是最好的,因为private构造方法后,可以避免new一个新对象,可是避免不了通过反射机制创建个新对象啊。

    • 还有我们用的说的第一种饿汉式,是在类被加载的时候,创建的实例对象,可是如果有两个类加载器呢,就不能保证对象的唯一性了。

    • 可是我们在必须使用单例的时候,我们为了避免不必要的错误,这里我们优先选择双重锁,静态内部类,大神特别推荐使用枚举。我觉得能高效解决问题的方法就是好方法。

    最后:有需要Shadowsock翻墙账号可以私聊。

    相关文章

      网友评论

      • 小鄧子:第三种其实算不上“单例设计模式”,设计模式是面向语言的,可能有些语言并不支持这种内部类的使用方式,不过至少在java中他是好用的,我也一直在使用,但如果需要初始化参数,可能有些麻烦。:pensive:
        小追兵:@小鄧子 嗯。设置set方法初始化,也可以吧?有什么问题?
        小鄧子:@小M的情怀 可以加一个全局的init或者在需要调用的方法上传入参数,不过,如果这样做,就不那么的像“单例”了。:pensive:
        小追兵:@小鄧子 嗯。是吗?你是怎么解决初始化参数的?
      • 曾樑::+1::+1:
        18ce9f6925e6:@小M的情怀 原来如此,怪不得觉着眼熟呢😊
        小追兵:@曾樑 抄来的,作为笔记记录下来。哈哈。

      本文标题:单例的几种常见写法

      本文链接:https://www.haomeiwen.com/subject/pdluhttx.html