设计模式(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;
    }
    
}

instance = new Singleton()不是一个原子操作,执行过程分为三步:

  1. 给Singleton的实例分配内存;
  2. 调用Singleton的构造函数,初始化成员字段;
  3. 将instance对象指向分配的内存空间(此时instance将不再是null)。

由于Java编译器存在指令重排序,也就是说上面的执行顺序无法得到保证,如果在执行完第三步时还没有来得及执行第二步就切换到其它线程,这是其它线程读取到的instance将会为null,DCL就会失效,当然在高并发的环境下发生的概率很小。

可以使用volatile来避免这个问题, 一旦一个共享变量(类的成员变量、类的静态成员变量)被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源码设计模式解析与实战》

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值