设计模式之单例模式

模式介绍

说起单例模式,相信对于从事开发的同学来说再熟悉不过了,单例模式是一种相对来说简单且应用最广泛的设计模式,该模式确保我们使用的单类对象类只有一个实例存在,避免创建过多对象实例造成资源浪费,熟悉Android开发的同学都知道,Android中Application类其实就属于单例模式,同时在平时开发中,我们也会将图片加载类、网络请求类、数据库操作类等等设计成单例模式。

模式定义

确保某一个类只有一个实例,而且自行实例化并向整个系统提供该实例对象,如何确保只有一个实例?让类自身负责保存该类的唯一实例,同时保证单例类的构造方法私有化,然后提供一个公开的静态方法访问这个唯一的实例。

实现方式

单例模式的实现方法有很多种,分别有饿汉模式、懒汉模式、DCL(双重解锁)模式、静态内部类模式、枚举单利模式、接下来我们一一介绍这几种模式,并分析每种模式的优缺点。

饿汉模式
public class Singleton {
    
    private Singleton() {
        
    }
    
    private static Singleton instance= new Singleton();
    
    public static Singleton  getInstance() {
        
        return instance;
    } 
        
}

饿汉模式在类加载的时候就对实例进行了初始化,由于单例对象一开始就得以创建,所以当我们调用起实例时,反应速度较快,同时饿汉模式也保证了实例对象的唯一性,多线程情况下不会创建多个实例对象。正是由于其在类加载的时候就创建了实例对象,所以不管我们有没有调用该单例对象,单例类都会去创建实例对象,从而造成了系统资源的浪费。

懒汉模式
public class Singleton {
    
    private Singleton() {
        
    }
    
    private static Singleton instance;
    
    public static synchronized Singleton  getInstance() {
        
        if (instance == null ) {
            instance = new Singleton();
        }
        
        return instance;
    } 
        
}

懒汉模式相比较饿汉模式来说,采用了懒加载的方式,只有在使用的时候才会进行实例化,节约了系统资源。同时在getInstance方法上加了synchronized 关键字来保证多线程调用,但是这样我们每次调用getInstance方法时都会进行同步,造成一些不必要的同步的开销,导致系统的性能受到一定的影响。

DCL(Double Check Lock)
public class Singleton {
    
    private Singleton() {
        
    }
    
    private static volatile Singleton instance;
    
    public static  Singleton  getInstance() {
        
        if (instance == null ) {
            synchronized (Singleton.class) {
                if (instance == null ) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }       
}

DCL单例实现方式同懒汉模式一样,第一次执行getInstance方法时对对象进行实例化,但相对懒汉模式来说,DCL对getInstance方法进行了优化,并没有像懒汉模式一样每次都进行同步来保证线程安全,而是进行了俩次的空判断,第一次判断空是为了避免进行不必要的同步,如果不为空,直接返回实例,第二次判空主要是为了创建实例对象,同时我们发现在静态成员变量instance前面加了一个volatile关键字,接下来详细分析下为什么加volatile?如果不加会有什么问题?
要分析以上问题,首先我们要了解对象的创建过程,实例化一个对象其实可以分为三个步骤,也就是说这行代码instance = new Singleton()其实是分了以下三步执行:

  1. 为SingleInstance的实例分配内存空间;
  2. 初始化对象(调用构造方法,初始化成员字段);
  3. 将分配好的内存空间赋值给对应的引用,也就是instance。
    这里不得不提到一个概念叫做指令重排序,首先这里不对指令重排序做详细介绍,现在来分析以上三个步骤执行顺序,如果上面三个步骤按照正常1-2-3来执行的话,不会发生任何问题,但是指令重排序可能会导致执行顺序变为1-3-2,假设我们现在有A、B俩个线程同时执行,如果A按照1-3-2顺序执行的话,当3执行完成后,这时instance已经不为空了,那么如果B这时候去获取该对象实例的话就会直接返回instance,这就使用时就会出错,造成DCL失效。当然我们这里加了volatile关键字后可以避免这种情况的发生,volatile关键字可以防止指令重排序,当然volatile还有其他作用,比如保证原子性、实现可见性。Java 并发编程:volatile的使用及其原理这篇文章对volatile关键字作了详细解释,感兴趣的同学可以去查看
静态内部类模式
public class Singleton {
    
    private Singleton() {
        
    }
    
    public static  Singleton  getInstance() {
        
        return SingletonHolder.instance;
    } 
    
    static class SingletonHolder {
        
        private static final Singleton instance = new Singleton();
    }
        
}

静态内部类是目前比较推崇的一种单例模式实现方式,首次加载类的时候并不会对实例进行初始化,只有在第一次调用getInstance方法时才会去加载SingletonHolder类 ,并对对象实例进行初始化,这种方式延迟了对象的实例化,同时保证了线程安全性与对象的唯一性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容