设计模式学习系列文章(第二篇:单例模式)

学习前言的废话

     单例模式是创建型模式中的一种,创建型模式的特点是将对象的创建与使用分离,基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式就是通过以某种方式控制对象的创建来解决问题,学习单例模式也是对创建型设计模式的一个初探,话不多说,单例究竟可以解决什么问题呢,我们现在开始学习。

单例模式的解读

经典定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

首先我们可以先解读一下单例这个概念,单例通俗的讲就是一个对象的实例在整个应用生命周期里只生成一次,所有的请求(方法调用)都是由这一个实例处理。举例来说就像是封建王朝中央集权的皇帝,只有一个,并且朝中大事必须得经过他的允准处理。所以,可以简单的说,单例模式就是创建这么一种对象的模式。
在这里插入图片描述

单例模式的应用

     单例模式的意思我们已经了解了,那大家可以思考一个问题,为什么在古代,一朝只有一个帝王呢?
     其实综合封建社会的历史因素,不难理解,帝王是一个强势的角色,坐拥江山,朝臣全都都听命于他,如果有多个帝王这样的角色,可以同时处理国家大事,国家内部势必会因抢夺资源而造成战争和破坏,因为不同意见而导致冲突,为了保证国家的长治久安,只能有且只有这么一个角色。
     结合我们的编程思想,我们什么时候需要帝王这样的一个角色呢?
     可能大家都有了一些想法,我说一下应用比较多的场景,一个是静态方法,常见于我们写的工具类中,再就是一些属性配置类,常见的数据库连接类等等。我在组件中的用到单例大多就是这样。
     总的来说,如果是贯穿程序始终的类,必然会频繁调用,如果每一次调用都要重新生成实例,带来的就是在内存堆中,分配一些内存空间,因此为了减少系统资源的消耗,提高程序的运行速度,我们就需要使用单例模式。

单例模式的分类跟特点

     有一种帝王时时刻刻在等待被召唤,准备好要登基为王,治国平天下。还有一种帝王,是赶鸭子上架,不到万不得已,不会让他来干活。这就是我们所说的饿汉式单例跟懒汉式单例,前者是提前做好一切准备,而后者则恰恰相反,需要时才被召唤。

懒汉式单例

     在多线程的使用过程中,考虑到线程安全的问题,我们深入了解一下懒汉式单例,看看如何让懒汉在多线程下安全。首先,我们在懒汉式单例中,实例化对象时,jvm做了三件事情,在堆里分配空间,调用私有构造函数进行初始化,将对象指向分配空间。但是生成汇编代码的时候并不一定会按照这个顺序去执行。如果实例不为空,但它还没执行构造方法进行初始化,该线程如果对那些需要初始化的参数进行操作那就GG了。所以如何解决这个问题呢?
    使用双检锁/双重校验锁(DCL,即 double-checked locking)机制,volatile +synchronized ,这种方式安全且在多线程情况下能保持高性能

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}
饿汉式单例

     我们可看到如果在多线程的情况下使用单例模式,懒汉式需要一DCL机制来保证线程安全。饿汉式恰恰可以解决这个问题,在定义的时候就将对象创建出来,不存在线程安全问题。那既然饿汉式这么简单粗暴,还要懒汉式干什么呢?
     存在即合理,这是亘古不变的真理,饿汉式并不是延迟加载的,类加载时就初始化,浪费内存并且容易产生垃圾对象,但是没有加锁,效率会比懒汉式强一些。并且假如在获取对象的时候,需要传一个参数进去呢?在获取实例对象时,需要传一个参数,针对这种情况,“饿汉式”就不行了,就得用“懒汉式”单例了。

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

比较主流的单例模式,工作中用得比较多的就是这两种,其他的例如枚举单例,这里只做简单介绍,通过 EnumSingleton.INSTANCE,即可获取到对象。

感兴趣的可以了解一下,非常简单粗暴

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

最后单例模式结构图,大家可以学习一下
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值