当前位置:网站首页 > 技术博客 > 正文

单例模式怎么写



廖雪峰
资深软件开发工程师,业余马拉松选手。

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式(Singleton)的目的是为了保证在一个进程中,某个类有且仅有一个实例。

因为这个类只有一个实例,因此,自然不能让调用方使用来创建实例了。所以,单例的构造方法必须是,这样就防止了调用方自己创建实例,但是在类的内部,是可以用一个静态字段来引用唯一创建的实例的:

那么问题来了,外部调用方如何获得这个唯一实例?

答案是提供一个静态方法,直接返回实例:

或者直接把变量暴露给外部:

所以,单例模式的实现方式很简单:

  1. 只有构造方法,确保外部无法实例化;
  2. 通过变量持有唯一实例,保证全局唯一性;
  3. 通过方法返回此唯一实例,使外部调用方能获取到实例。

Java标准库有一些类就是单例,例如这个类:

有些童鞋可能听说过延迟加载,即在调用方第一次调用时才初始化全局唯一实例,类似这样:

遗憾的是,这种写法在多线程中是错误的,在竞争条件下会创建出多个实例。必须对整个方法进行加锁:

但加锁会严重影响并发性能。还有些童鞋听说过双重检查,类似这样:

然而,由于Java的内存模型,双重检查在这里不成立。要真正实现延迟加载,只能通过Java的ClassLoader机制完成。如果没有特殊的需求,使用Singleton模式的时候,最好不要延迟加载,这样会使代码更简单。

另一种实现Singleton的方式是利用Java的,因为Java保证枚举类的每个枚举都是单例,所以我们只需要编写一个只有一个枚举的类即可:

枚举类也完全可以像其他类那样定义自己的字段、方法,这样上面这个类在调用方看来就可以这么用:

使用枚举实现Singleton还避免了第一种方式实现Singleton的一个潜在问题:即序列化和反序列化会绕过普通类的构造方法从而创建出多个实例,而枚举类就没有这个问题。

那我们什么时候应该用Singleton呢?实际上,很多程序,尤其是Web程序,大部分服务类都应该被视作Singleton,如果全部按Singleton的写法写,会非常麻烦,所以,通常是通过约定让框架(例如Spring)来实例化这些类,保证只有一个实例,调用方自觉通过框架获取实例而不是操作符:

因此,除非确有必要,否则Singleton模式一般以“约定”为主,不会刻意实现它。

使用两种Singleton模式实现单例。

下载练习

Singleton模式是为了保证一个程序的运行期间,某个类有且只有一个全局唯一实例;

Singleton模式既可以严格实现,也可以以约定的方式把普通类视作单例。

  • 上一篇: jdk8 hashmap的改进
  • 下一篇: 小程序源码商城
  • 版权声明


    相关文章:

  • jdk8 hashmap的改进2025-03-05 16:30:02
  • 抓包工具Charles2025-03-05 16:30:02
  • excel对比功能2025-03-05 16:30:02
  • 二阶低通滤波器电路2025-03-05 16:30:02
  • python游戏编程教程2025-03-05 16:30:02
  • 小程序源码商城2025-03-05 16:30:02
  • 手写数字 数据集2025-03-05 16:30:02
  • 接口自动化测试平台搭建2025-03-05 16:30:02
  • 类的静态成员变量怎么赋值2025-03-05 16:30:02
  • 开窗函数 lag2025-03-05 16:30:02