精讲Android设计模式-单例模式

作者: TryEnough | 来源:发表于2019-02-12 14:37 被阅读30次

    原文链接

    更多教程


    为什么要使用单例模式

    单例的优点

    1.只有一个实例,节省开销
    2.全局使用方便,同时避免频繁创建和销毁

    使用单例的注意点:
    要避免造成 内存泄漏

    常用的单例模式

    单例不仅要满足线程安全,还要注意防止序列化产生新对象。如果单例实现了Serializable接口,就必须加入如下方法(枚举单例不用这么做,因为JVM能保障这点):

    private Object readResolve()  throws ObjectStreamException{
        return INSTANCE;
    }
    

    原文链接

    更多教程


    饿汉式

    饿汉式:就是在类初始化时就实例化,所以是线程安全的。
    缺点是:
    1.没有懒加载,在不需要的时候也会被实例化,造成内存浪费。
    2.实例化方法对外部调用不友好,传参不方便

    public class Singleton implements Serializable {
        private static final Singleton INSTANCE = new Singleton();
        // 私有化构造函数
        private Singleton(){}
    
        public static Singleton getInstance(){
            return INSTANCE;
        }
    
        /**
         * 如果实现了Serializable, 必须重写这个方法
         */
        private Object readResolve() throws ObjectStreamException {
            return INSTANCE;
        }
    }
    

    懒汉式

    延迟加载(使用时加载),节省内存
    双重判空,第一次判空防止重复加锁,第二次判空才实例化
    防止DCL指令重拍序,加volatile关键字

    public class Singleton {
        private volatile static Singleton INSTANCE; //声明成 volatile
        private Singleton (){}
    
        public static Singleton getSingleton() {
            if (INSTANCE == null) {                         
                synchronized (Singleton.class) {
                    if (INSTANCE == null) {       
                        INSTANCE = new Singleton();
                    }
                }
            }
            return INSTANCE;
        }
    
    }
    
    //如果实现了Serializable, 必须重写同上面饿汉式一样的readResolve方法
    

    枚举式

    由JVM保证线程安全
    序列化和反射攻击已经被枚举解决

    //enum枚举类
    public enum Singleton { 
        INSTANCE;  
        public void yourMethod() {  
    
        }  
    }
    

    内部类实现单例

    当Singleton被加载时,其内部类并不会被初始化,故可以确保当 Singleton类被载入JVM时,不会初始化单例类。只有 getInstance() 方法调用时,才会初始化 instance。同时,由于实例的建立是时在类加载时完成,故天生对多线程友好,getInstance() 方法也无需使用同步关键字。

    public class Singleton { 
        /** 
         * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系, 
         * 而且只有被调用到才会装载,从而实现了延迟加载 
         */ 
        private static class SingletonHolder{ 
            /** 
             * 静态初始化器,由JVM来保证线程安全 
             */ 
            private static final Singleton instance = new Singleton(); 
        } 
        /** 
         * 私有化构造方法 
         */ 
        private Singleton(){ 
        } 
    
        public static  Singleton getInstance(){ 
            return SingletonHolder.instance; 
        } 
    }
    

    原文链接

    更多教程


    相关文章

      网友评论

        本文标题:精讲Android设计模式-单例模式

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