创建篇-单例模式

Posted zhixuChen333

tags:

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

文章目录


前言

单例模式(Singleton)是一种非常简单且容易理解的设计模式。顾名思义,单例即单一的实例,确切地讲就是指在某个系统中只存在一个实例,同时提供集中、统一的访问接口,以使系统行为保持协调一致。singleton一词在逻辑学中指“有且仅有一个元素的集合”,这非常恰当地概括了单例的概念,也就是“一个类仅有一个实例”。


提示:以下是本篇文章正文内容,下面案例可供参考

一、饿汉式

这就是“饿汉模式”(eager initialization),即在初始阶段就主动进行实例化,并时刻保持一种渴求的状态,无论此单例是否有人使用。

public class Singleton2 
    private static final Singleton2 instance = new Singleton2();

    private Singleton2() 
    

    public static Singleton2 getInstance() 
        return instance;
    


要点:

  1. 构造方法私有,这样实例化工作完全归属于内部事务,任何外部类都无权干预。
  2. 实例私有,确保实例的私有性、不可见性和不可访问性。
  3. "static"关键字保证实例在类加载的时候就初始化,不会被GC回收。
  4. "final"关键字保证实例是个常量,一旦赋值后不能被修改。

二、懒汉式

1.有缺陷的懒汉式

如代码所示,只有在某线程第一次调用getInstance()方法时才会运行对该类进行实例化的逻辑代码,之后再请求就直接返回此实例了。这样的好处是如无请求就不实例化,节省了内存空间。这样的程序逻辑看似没问题,但其实在多线程模式下是有缺陷的。试想如果是并发请求的话,程序判空逻辑就会同时成立,这样就会多次实例化,并且对instance进行多次赋值(覆盖)操作,这违背了单例的理念。

public class Singleton1 
    private static Singleton1 instance;

    private Singleton1() 
    

    public static Singleton1 getInstance() 
        if (instance == null) 
            instance = new Singleton1();
        
        return instance;
    

2.改进后的懒汉式

大家注意到没有,我们一共用了2个嵌套的判空逻辑,这就是懒加载模式的“双检锁”:外层放宽入口,保证线程并发的高效性;内层加锁同步,保证实例化的单次运行。如此里应外合,不仅达到了单例模式的效果,还完美地保证了构建过程的运行效率,一举两得。

public class Singleton3 
    private static Singleton3 instance;

    private Singleton3() 
    

    public static Singleton3 getInstance() 
        if (instance == null) 
            synchronized (Singleton3.class) 
                if (instance == null) 
                    instance = new Singleton3();
                
            
        
        return instance;
    

要点:

  1. “synchronized”关键字,不添加在方法上而是锁同步代码块,减小锁的粒度,提高效率。

总结

提示:这里对文章进行总结:

  1. 相比“懒汉模式”,其实在大多数情况下我们通常会更多地使用“饿汉模式”,原因在于这个单例迟早是要被实例化占用内存的,延迟懒加载的意义并不大,加锁解锁反而是一种资源浪费,同步更是会降低CPU的利用率,使用不当的话反而会带来不必要的风险。越简单的包容性越强,而越复杂的反而越容易出错、
  2. 除了“饿汉”与“懒汉”这2种单例模式,其实还有其他的实现方式。但万变不离其宗,它们统统都是由这2种模式发展、衍生而来的。我们都知道Spring框架中的IoC容器很好地帮我们托管了业务对象,如此我们就不必再亲自动手去实例化这些对象了,而在默认情况下我们使用的正是框架提供的“单例模式”。

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

自己动手实现牛逼的单例模式

原创自己动手实现牛逼的单例模式

设计模式系列篇——单例模式

从零开始学习Java设计模式 | 创建型模式篇:单例设计模式

从零开始学习Java设计模式 | 创建型模式篇:单例设计模式

原创自己动手循序渐进实现观察者模式