美文网首页
单例模式 (Singleton)

单例模式 (Singleton)

作者: kinglong1984 | 来源:发表于2018-10-14 11:04 被阅读4次

    本文主要根据以下著作中的内容整理而来:

    何红辉,关爱民.Android源码设计模式解析与实践第2版〔M〕.北京:人民邮电出版社,2017.7

    定义

    确保某一个类只有一个实例,自行实例化并向整个系统提供这个实例。

    角色

    Client——高层客户端。

    Singleton——单例类。

    特点

    私有:构造方法是私有的,静态变量是私有的。

    静态:通过一个公有的静态方法或枚举返回单例类对象。

    线程安全:多线程环境下也要确保对象只有一个。

    几种实现方式

    以下几种方式在初始化静态对象上有不同。

    饿汉模式:声明静态对象时直接初始化。new的过程很耗时的话,应用程序启动的会很慢,降低体验的友好性

    懒汉模式:声明一个静态对象,在用户第一次调用getInstance()时初始化。延迟单例的实例化。

                    懒汉模式 问题:getInstance的调用频率很高的话,每次都synchronized同步访问,效率低。

    双重检查锁定(DCL):既能在需要时初始化,又能保证线程安全,消除懒汉模式中重复同步问题。(得比较多的方式,JDK1.5及以上版本使用volatile,没有复杂的并发场景下一般能满足使用)

    静态内部类:解决双重检查锁定失效问题。(推荐使用的实现方式)

    代码示例

    双重检查锁定方式:

    public class Singleton{

        //问题1:new操作的反汇编代码,其实他包含3条汇编指令:new、dup、init。sInstance 不为null并不保证sInstance是完整地初始化好了成员。

        // 问题2:即使一个线程实例化了sInstance ,由于每个线程都有自己的working缓存,可能另一个线程看不到前一个线程对sInstance 的操作。

        // JDK1.5及以后 使用volatile关键字,保证每次sInstance都是从主内存中获取。

        private volatile static Single sInstance = null;

        private Singleton(){}

        public static Singleton getInstance(){

            if(sInstance==null){

                synchronize(Singleton.class){

                    if(sInstance==null){

                           sInstance = new Singleton();//实际上不是一个原子操作:1.给Singleton实例分配内存;2.调用Singleton()构造方法初始化成员字段;3.将sInstance指向分配的内存空间。 执行顺序可能是1-2-3或者1-2-3。

                    }

                }

            }

        }

    }

    静态内部类方式:

    public class Singleton{

        private Singleton(){}

        public static Singleton getInstance(){

            // 延迟初始化

            return SingletonHolder.sInstance;

        }

       private static class SingletonHolder{

            //静态变量是线程共享的,保证了单例的线程安全。避免了双重检查锁定失效问题。

            private static final Singleton sInstance = new Singleton();

        }

    }

    扩展应用

    使用容器实现单例

    Android Context的实现类ContextImpl

    public class ContextImpl extends Context {

        private final static Map<String,ServiceFetcher> SYSTEM_SERVICE_MAP= new HashMap<String,ServiceFetcher>();

        public static void registerService(String serviceName,ServiceFetcher fetcher){

            //省略代码

            SYSTEM_SERVICE_MAP.put(serviceName,fetcher);

        }

        public Object getSystemService(String key){

            ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(key);

            return fetcher ==null? null:fetcher.getService(this)

        }

        static {

            registerService(LAYOUT_INFLATER_SERVICE,new ServiceFetcher(){

                public Object createService(ContextImpl ctx){

                    return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());

                }

            })

        }

    }

    相关文章

      网友评论

          本文标题:单例模式 (Singleton)

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