单例设计模式

既然来了简书,总要留下点什么.......

读书养才气,勤奋养运气,宽厚养大气,淡泊养志气

倚天屠龙记.jpg

1-What

保证一个类在任何情况下在程序中都绝对只有一个实例,并且提供一个全局访问点。

2-Premise

1.构造函数私有,防止被外部new对象;
2.内部必须提供一个静态的方法,让外部调用。

3-Advantage

减少内存开销;
避免资源多重占用。

4-Disadvantage

不易扩展。

5-Classify

5-1-饿汉式

类加载过程中,就已经创建了实例。

public class SingletonE {
    //静态修饰的实例,类在加载时就是执行实例化操作
    private static SingletonE mInstance = new SingletonE();
    //构造函数私有化,使外界无法创建实例
    private SingletonE(){
    }
    //为外界提供获取实例的方法
    public static SingletonE getInstance(){
        return mInstance;
    }
}

也可以通过静态代码块方法初始化。

不足:浪费内存空间;代码不灵活。

5-2-懒汉式

当需要使用类的时候,才去实例化。

public class SingletonL {

    private static SingletonL mInstance;

    private SingletonL(){}

    public static SingletonL getInstance(){
        if (mInstance == null){ //null判断
            mInstance = new SingletonL();
        }
        return mInstance;
    }
    
}

不足:多线程中不能保证只创建一次实例。(多线程并发)
解决方法:加锁——synchronized

public synchronized static SingletonL getInstance(){
        if (mInstance == null){ //null判断
            mInstance = new SingletonL();
        }
        return mInstance;
}

不足:虽然解决了线程安全的问题,但是方法每次调用的时候,都会进行同步检查,造成效率低。
解决方法:双重检查锁——减少同步检查范围

public static SingletonL getInstance(){
        if (mInstance == null){
            synchronized (SingletonL.class){ //同步检查
                if (mInstance == null){
                    mInstance = new SingletonL();
                }
            }
        }
        return mInstance;
    }

不足:mInstance可能未初始化,用户获取的对象是空的
原因:Java虚拟机的指令:
1.给对象分配内存;
2.调用方法初始化对象;
3.将对象与内存关联,赋值。
但是Java多线程中,步骤2和3的执行顺序不是固定的。

解决方法volatile的使用 1.防止重排序;2.保证对象可见性。某一线程改了变量,短时间内该变量在另一个线程可能是不可见的,因为每一个线程都有自己的缓存区。

private static volatile SingletonL mInstance;
5-3-静态内部类
public class SingletonS {
    private SingletonS(){

    }

    public static SingletonS getInstance(){
        return SingletonHolder.mInstance;
    }

    public static class SingletonHolder{
        private static SingletonS mInstance = new SingletonS();
    }
}

好处:既保证线程安全,又实现了懒加载。

5-4-静态代码块结合容器(HashMap)
 private static Map<String,Object> map = new HashMap<>();
 static {
     map.put("single",new SingletonS());
 }

除了上述的几种方式外,枚举也能实现单例,而且是最简单的,但是也存在一种问题——代码不灵活。所以,究竟选择哪一种方式实现单例,还是根据开发者自己以及项目需求。

6-Where

Activity管理

参考文章:

https://segmentfault.com/a/1190000018494382
https://blog.csdn.net/qq_25333681/article/details/93662660

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容