单例模式实战

Posted 雨夜随笔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式实战相关的知识,希望对你有一定的参考价值。

单例模式中我们简单说了单例模式的概念和应用场景,在实际使用中,我们想要更好的使用单例模式,还需要注意一些其他的问题。



实现方式


懒汉式


单例模式中我们介绍了单例模式的一种实现方式--懒汉式:

public class SingletonObject {
    private static SingletonObject instance;
    
    public static SingletonObject getInstance() {
        if (null == instance) {
            instance = new SingletonObject();
        }
        return instance;
    }
}


这种就是懒加载或者延迟加载的方式,等到需要使用的时候再创建单例对象。这种方式的好处是不会一直占用系统资源,只有使用时才会开始占用。


缺点也很明显,主要是线程不安全,所以一般会在创建前加一把锁,有时因为语言重排序的原因,导致创建方法还没来得及创建就被其他线程使用。这时需要手动处理这种情况。


饿汉式


还有一种是在加载的时候就创建好对象,所以这种创建方式是线程安全的。

public class SingletonObject {
    private static final SingletonObject instance = new SingletonObject();
    
    public static SingletonObject getInstance() {
        return instance;
    }
}


这种方式也存在一定的缺点,那就是会占用资源,这个需要在设计时考虑,如果创建过程很耗时或者耗资源,那么采用饿汉式方式是一种很好的方式,这样不会因为占用太多时间或者资源不足而无法创建。


其他方法


当然还有其他方法来使用单例模式,这里主要和具体的语言实现有关,比如Java中就存在静态内部类的方法和枚举方法:

// 静态内部类
public class SingletonObject {
    private static class SingletonObjectHolder {
        private static SingletonObject instance = new SingletonObject();
    }
    
    public static SingletonObject getInstance() {
        return SingletonObjectHolder.instance;
    }
}

// 枚举类
public enum SingletonObject {
    INSTANCE;
}


一般来说这种方式会更好,因为语言内部对这种做了很好的支持。当然这些一般都是随着需求的使用来选择。


我们重点关注懒汉式和饿汉式的使用方式,这两种的选择主要是衡量创建和运行时占用的资源。两种并没有那种最好,我们应根据具体的业务需求来选择我们的方式。


注意事项



单例模式可以说争议非常大,因为一方面是单例模式的使用方便,并且可以解决全局唯一的情况。但是单例模式有很多问题:
  • 单例会使得依赖关系变得复杂:一般来说,我们可以通过类的声明来查看类的依赖关系,但是由于单例不需要声明和创建。所以导致最终我们不知道具体的依赖关系,必须要查看具体的实现代码才能知道依赖细节。

  • 单例使得生命周期变得复杂:单例一般来说一次创建,就不再销毁。这种时候一旦在单例创建里面增加额外的操作,那么它的生命周期将变得复杂。特别是像android这种,单例的生命周期并不一定是和应用生命周期一致。这就导致很多意外的情况发生。

  • 单例对OOP的支持不好:单例可以说是违背OOP的抽象,继承和多态。因为单例没有基于接口的原则进行实现。同样对于继承和多态,虽然可以实现,但是会让代码变得很奇怪,可读性很差。

  • 单例对后续修改不太友好:一旦我们对单例的需求发生改变,比如需要增加对象的实例,那么就需要重构单例对象的逻辑,并修改所有调用的地方,这就导致代码的改动太多

  • 单例不支持有参数的创建方式:严格来说可以通过某种方式来实现单例的有参数创建方式,但是这就和单例模式的初衷相违背了,也就是全局唯一。当我们用新的参数去创建后,可能新的参数并不会起效。


所以基于上面这些原因,很多人不推荐使用单例模式,甚至认为这个不应该在项目中使用。但是实际上任何设计模式都有其优缺点,不能一概而论的认为那种好,那种不好。应当根据具体的场景来使用和组合设计模式。

总结


单例模式理解起来并没有很复杂,使用起来也很方便。但最重要的是理解单例模式的适用场景,并且管理好单例模式的影响范围。不要在单例中增加过多的额外依赖或者对象创建。


以上是关于单例模式实战的主要内容,如果未能解决你的问题,请参考以下文章

单例模式实战

spark 大型项目实战:用户访问session分析 --单例模式

spark 大型项目实战:用户访问session分析 --单例模式

设计模式之单例模式

单例模式在项目实战中的几个应用

单例模式在项目实战中的几个应用