• android源码设计模式学习之单列模式


    单列对象的类必须保证一个实例存在,而且自行实例化并向整个系统提供这个实例

    使用场景:确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个,如访问数据库

    使用单列模式的关键点:
    (1)构造函数不对外开放,一般为private
    (2)通过一个静态方法或者枚举返回单列对象
    (3)确保单列对象有且只有一个,尤其多线程环境下
    (4)确保单列对象在反序列化时不会重新构建对象

    (一)饿汉式

    public class IOUtil {
        private static final IOUtil INSTANCE = new IOUtil();
        private IOUtil(){}
        public static IOUtil getInstance(){
            return INSTANCE;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (二)懒汉式
    是声明一个静态对象,并且在用户第一次调用getInstance时初始化

    public class IOUtil {
        private static IOUtil INSTANCE = null;
        private IOUtil(){} 
        public static synchronized IOUtil getInstance(){
            if (INSTANCE == null){
                INSTANCE = new IOUtil();
            }
            return INSTANCE;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    getInstance()方法中添加一个synchronized关键字,也就是getInstance的一个同步方法,者就是在多线程情况下保证单列对象唯一性的手段。但是,每次使用getInstance时都会synchronized同步,会造成不必要的同步开销,所以建议不使用多线程时,不使用该关键字

    (三)DCL实现单列
    DCL实现单例模式的优点是既能在需要时才初始化单列,又能保证线程安全,且单列对象初始化后调用getInstance不进行同步锁

    public class IOUtil {
        private static IOUtil INSTANCE = null ;
    
        private IOUtil(){}
    
        public static IOUtil getInstance(){
            if (INSTANCE == null){
                synchronized (IOUtil.class){
                    if (INSTANCE == null){
                        INSTANCE = new IOUtil();
                    }
                }
            }
            return INSTANCE;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    优点:资源利用率高
    缺点:第一次加载时反应慢

    (四)静态内部类单列模式
    DCL虽然在一定程度上解决了消耗资源,多余的同步,线程安全等问题,但是,它还是在某些情况下出现失效的问题,不赞成使用

    public class IOUtil {
    
        public static IOUtil getInstance(){
            return SingleHolder.INSTANCE;
        }
        
        private static class SingleHolder{
            public static final IOUtil INSTANCE = new IOUtil();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    当第一次加载IOutil类时并不会初始化INSTANCE ,只有在第一次调用getInstance时才会导致INSTANCE被初始化,这种方式不仅保证线程安全,也能保证单例对象的唯一性,推荐使用。

    (五)使用容器实现单例模式

    public class IOUtil {
        private static HashMap<String,Object> hashMap = new HashMap<>();
    
        public static void registerService(String key,Object object){
            if (!hashMap.containsKey(key)){
                hashMap.put(key,object);
            }
        }
    
        public static Object getService(String key){
            return hashMap.get(key);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Android源码中的单列模式
    在Android系统中,我们经常会通过Context获取系统级别的服务,如WindowManagerService ,ActivityManagerService等。更常用的是LayoutInflater的类,LayoutInflater较为常见的地方是在ListView的getView方法中

    View view = LayoutInflater.from(mContext).inflate(layoutId,null);
    
    • 1

    可以看到的form(Context)函数内部调用的是Context类的getSystemService(String key)方法,我们继续看

  • 相关阅读:
    Docker 命令
    学习笔记二十三:Deployment入门到企业实战应用
    C# 子类如何访问子类的方法(同一父类)
    Vulnhub系列靶机---Raven2
    嵌入式软件开发常用的3种架构
    电流检测放大器
    CREO:CREO软件之零件【模型】之操作、基准、形状、扫描、工程、编辑、曲面的简介及其使用方法(图文教程)之详细攻略
    SSM框架学习——MyBatis Plus
    [100天算法】-第一个错误的版本(day 62)
    Flink系列之Flink中RestartStrategy重启策略和FailoverStrategy故障转移策略
  • 原文地址:https://blog.csdn.net/qq_42447739/article/details/126256178