设计模式之单例模式

1. 要求

确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

1.1 构造方法的要求

确保一个类只有一个实例,那么就要求它的构造方法一定不能是public公开的,即不能被外界进行实例化。那么他的构造方法只能是private

1.2 实例的要求

接着,他只有一个实例,这个实例属于当前类,即这个实例是当前类的类成员变量静态变量

类变量其实就是静态变量,即用static修饰。通过上半部分可以看出这种设计模式要求构造方法是private,并且拥有一个当前类的静态成员变量。

后面他要求向整个系统提供这个实例,即我们要再提供一个静态的方法, 来向外界提供当前类的实例。当前实例只能在内部进行实例化,它不能够放到外面去。

2. 使用场景

单例模式的主要作用是确保一个类只有一个实例存在,比如说序列号生成器Web页面的计数器等等都可以使用单例模式。同时如果创建某个对象需要消耗较多资源的话,比如访问IO、或者数据库资源的时候,我们也可以使用单例模式来减少资源的消耗。

3. 实例化的时间不同

对于一个实现了单例模式的类来说,它首先构造方法必须是私有的,即Private。接着,它拥有一个唯一的实例,即它的类变量,静态变量,用static修饰的。但是我们singleton在什么时候进行实例化。可以看到它刚开始是空的,根据实例化实际不同。

4. 单例模式的分类

其实单例模式可以分为两种,饿汉式懒汉式

饿汉式,即在类加载的时候就进行实例化

懒汉式,即在类加载的时候不进行实例化,在第一次使用的时候再进行实例化。在这里如果singleton等于空的时候,将其进行实例化。这里需要加锁来防止它被多次实例化。

4.1 饿汉模式

还没等你去调用,它就先给你创建出来。就比如说先可以static等于,然后你创建的那个Instance对象直接给你声明出来了。

4.2 懒汉模式

可以用到内部类,内部类有一个好处,利用了类在加载的特性,只有类被利用到的时候,它才会被加载,而且只能加载一个。因为这个是根据ClassLoader来实现的。这是它们底层的东西了。

5. 为什么会出现多次实例化

两个线程同时执行完非空判断之后。因为两者开始均为空,所以两者都要进行实例化。如果不做同步的话,则需要实例化两次。所以我们加锁,来保证singleton只会被实例化一次。

6. 双重检查锁

懒汉式实现模式中非常经典的实现模式

首先,我们可以看到在做同步处理的范围是整个方法,但是我们的实例化仅仅发生在第一次。一旦被实例化之后,下次判断就不可能为空了,就不会进行实例化了。

但是我们还是会执行同步块,可以减小同步的范围,即在第一次判断为空的时候,我们就加锁以便实例化,接着内部再进行一个判断,如果还为空的话,则进行实例化。这个称之为双重检查锁

使用双重检查锁进行初始化的实例必须使用Volatile关键字修饰。

7. 实例化的三个步骤

new Singleton的时候是进行了三次操作:

  1. 第一步是分配内存
  2. 第二步是初始化对象
  3. 第三步是指向刚分配的地址

8. 提高获取实例的速度

通过处理,我们可以看到getInstance方法不再是同步方法,它的同步处理也仅仅放在第一次初始化的时候。这样可以提高我们获取实例时候的返回速度。

9. 出现多个实例的情况

单例模式的实例是全局唯一的,但是在以下两种情况下也会出现多个实例:

  1. 第一个是在分布式系统中,会有多个JVM虚拟机,各个虚拟机都有一个实例
  2. 同一个JVM虚拟机使用了多个类加载器同时加载这个类,产生了多个实例。

10. 严重问题

如果它有状态的话,比如它有一个字段(value)等于10,那我在某一个地方用的时候,先把它修改成20,接着我再执行逻辑。但是因为它只有一个实例,所以说其他地方在调用这个单例时候,它也可以随时对这个值进行修改,比如说改成30。

所以说单例模式最佳实践就是无状态的。比如以工具类的形式提供

11. 优点

  1. 在内存中只有一个对象,节省内存空间。
  2. 避免频繁的创建销毁对象,可以提高性能。
  3. 避免对共享资源的多重占用
  4. 可以全局访问。

参考资料

  1. 五分钟学设计模式.01.单例模式
  2. 单例模式5:优点
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值