美文网首页
单例模式

单例模式

作者: 刘孙猫咪 | 来源:发表于2017-09-22 08:23 被阅读0次

    单例模式,是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例的特殊类,通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例。

    第一种:饿汉式

    public class SingleEasy {
        private SingleEasy(){
    
        }
        //类初始化的时候就已经加载
        private static SingleEasy singleEasy=new SingleEasy();
        public static SingleEasy getInstance(){
            return singleEasy;
        }
    }
    

    饿汉式的话不存在多线程同步加载的问题,类初始化时就已经加载,做不到使用的时候才加载。

    第二种:懒汉式(线程不安全)

    public class SingleNotEmptyEasy {
        private static SingleNotEmptyEasy singleNotEmptyEasy;
        private SingleNotEmptyEasy(){
    
        }
        public static SingleNotEmptyEasy getInstance(){
            //对象为空才去实例化
            if(singleNotEmptyEasy==null){
                singleNotEmptyEasy=new SingleNotEmptyEasy();
            }
            return singleNotEmptyEasy;
        }
    }
    

    懒汉式是在使用的时候才会去加载,不过当多次同时去加载的时候就会存在线程安全问题。

    第三种:懒汉式(线程安全)

    public class SingleNotEmptyEasy {
        private static SingleNotEmptyEasy singleNotEmptyEasy;
        private SingleNotEmptyEasy(){
    
        }
        public static synchronized  SingleNotEmptyEasy getInstance(){
            //对象对空才去实例化
            if(singleNotEmptyEasy==null){
                singleNotEmptyEasy=new SingleNotEmptyEasy();
            }
            return singleNotEmptyEasy;
        }
    }
    

    就是在第二种的getInstance方法上面加了一个同步锁synchronized,每次在使用加载的时候都会先去校验,如果已经有在加载了,就不会去加载,而是要等前面的加载完了,才会去加载,这样线程安全,但是每次都去校验synchronized会造成效率的下降。

    第四种:DCL

    public class DCLSingle {
        private volatile static DCLSingle dclSingle;
        private DCLSingle(){
    
        }
        public static DCLSingle getInstance(){
            if(dclSingle==null){
                synchronized (DCLSingle.class){
                    if(dclSingle==null){
                        dclSingle=new DCLSingle();
                    }
                }
            }
            return dclSingle;
        }
    }
    

    DCL模式的不同是没有将同步锁加载方法上,而是加在代码块里面,如果单例对象不为空就直接返回,如果为空就会走到加了同步锁的代码块中,还会进行第二次校验,这样子提高了效率,同时也保证了线程的安全,这种模式还涉及到一个java的关键字volatile,加了volatile,可以保证无论何时读取这个变量,都是读到内存中最新的值,无论何时写这个变量,都可以立即写到内存中。

    第五种:内部类模式

    public class InnnerClassSingle {
        private InnnerClassSingle(){
    
        }
        private static class SingleHolder{
            private static InnnerClassSingle innnerClassSingle=new InnnerClassSingle();
        }
        public static InnnerClassSingle getInstance(){
            return SingleHolder.innnerClassSingle;
        }
    }
    

    内部类模式是一种比较优雅的饿汉式,它是在InnnerClassSingle内中再建一个SingleHolder内部类,在内部类中创建一个InnnerClassSingle对象,通过内部类调用加载实例化,这样子不会随着类的加载的而实例化,做到了使用的时候才实例化。

    第六种:枚举模式

    public enum  EnumManager {
        SDCardManager(10){
            @Override
            public EnumManager getSingle() {
                return SDCardManager;
            }
        }
        ,
        HttpManager(1){
            @Override
            public EnumManager getSingle() {
                return HttpManager;
            }
        };
        
        public abstract EnumManager getSingle();
        private EnumManager(int type){
    
        }
    }
    

    这里需要注意的是枚举的构造方法是私有的,变量的声明要在构造方法之前。

    相关文章

      网友评论

          本文标题:单例模式

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