设计模式(DesignPattern)之单例模式(SingleTon)

1、定义

        单例模式属于创建型模式,确保一个类只有一个实例,并提供一个全局的访问接口。

2、使用场景        

        在开发工程中,有些对象我们只需要一个:线程池、缓存、硬件设备等, 创建多个实例则会造成结果的不一致和资源的过多消耗。

3、UML类图


4、经典的实现方式

1、懒汉模式
/**
 * 懒汉模式
 */
public class SingleTon01 {

    private static SingleTon01 instance;

    private SingleTon01() {
    }

    public static synchronized SingleTon01 getInstance() {
        if (instance == null) {
            instance = new SingleTon01();
        }
        return instance;
    }
    
}

        懒汉模式在使用的时候才进行实例化,在一定程度上节约了资源,但是在每次调用getInstance()都进行了同步,造成不必要的同步。

2、Double Check Lock(DCL)模式
/**
 * Double Check Lock(DCL)双锁检测
 */
public class SingleTon02 {

    private volatile static SingleTon02 instance;

    /**
     * 构造方法私有化,不允许外部创建对象
     */
    private SingleTon02() {
    }

    public static SingleTon02 getInstance() {
        if (instance == null) {//第一次判空避免不必要的同步
            synchronized (SingleTon02.class) {
                if (instance == null) {//第二次判空为了在null的情况下创建实例
                    instance = new SingleTon02();
                }
            }
        }
        return instance;
    }
    
}
    DCL是使用最多的一种实现单例的方式,但在《Java并发编程实战》中提到这是一种"糟糕"的优化,在java1.5以前的版本中并没有真正解决线程同步问题,在1.5版本以后可以加上volatile

3、静态类部类模式
/**
 * 静态类部类模式
 */
public class SingleTon03 {

    private SingleTon03() {
    }

    private static class SingletonHolder {
        private static final SingleTon03 instance = new SingleTon03();
    }

    public static SingleTon03 getInstance() {
        return SingletonHolder.instance;
    }

}
        这种方式不仅能够保证线程安全,同时也能够保证单例对象的唯一性,延迟单例对象的实例化。
 4、枚举实现单例
/**
 * 枚举单例
 */
public enum SingleTon04 {

    INSTANCE;

}
        枚举对象的创建是现成安全的,并且也是唯一的。
5、利用容器实现单例
/**
 * 利用容器实现单例
 */
public class SingleTon05 {

    private static Map<String, Object> objMap = new HashMap<>();

    private SingleTon05() {}

    public void addObj(String key, Object instance) {
        if (!objMap.containsKey(key)) {
            objMap.put(key, instance);
        }
    }

    public static Object getObj(String key) {
        return objMap.get(key);
    }

}

        我们可以通过这种方式管理多种类型的管理,如对activity的管理。

5、总结

    优点:1、全局只有一个实例,减小了系统性能开销。

    缺点:1、扩展困难,只能通过修改代码的方式进行扩展。

              2、如果单例持有Context对象,容易造成内存泄漏问题,一般传递Application对象。


代码:https://gitee.com/os2chen/DesignPattern


参考:《Head First Design》、《Android源码设计模式解析与实战》







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章