在 Java 中应用设计模式 -- Singleton

2001 年 8 月 05 日

本文介绍了设计模式中 Singleton 的基本概念,对其功能和用途进行了简单的分析,列出了通常实现 Singleton 的几种方法,并给出了详细的Java 代码.

<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

基本概念

Singleton 是一种创建性模型,它用来确保只产生一个实例,并提供一个访问它的全局访问点.对一些类来说,保证只有一个实例是很重要的,比如有的时候,数据库连接或 Socket 连接要受到一定的限制,必须保持同一时间只能有一个连接的存在.再举个例子,集合中的 set 中不能包含重复的元素,添加到set里的对象必须是唯一的,如果重复的值添加到 set,它只接受一个实例.JDK中正式运用了Singleton模式来实现 set 的这一特性,大家可以查看java.util.Collections里的内部静态类SingletonSet的原代码.其实Singleton是最简单但也是应用最广泛的模式之一,在 JDK 中随处可见.

 




简单分析

为了实现 Singleton 模式,我们需要的是一个静态的变量,能够在不创建对象的情况下记忆是否已经产生过实例了.静态变量或静态方法都可以在不产生具体实例的情况下直接调用,这样的变量或方法不会因为类的实例化而有所改变.在图1的结构中可以看到,uniqueInstance 就是这个独立的静态变量,它可以记忆对象是否已经实例化了,在静态方法 Instance 中对这个变量进行判断,若没有实例化过就产生一个新的对象,如果已经实例化了则不再产生新的对象,仍然返回以前产生的实例.


图1: Singleton 模式结构
图1: Singleton 模式结构




 

具体实施

实现 Singleton 模式的办法通常有三种.

一. 用静态方法实现 Singleton 这种方法是使用静态方法来监视实例的创建.为了防止创建一个以上的实例,我们最好把构造器声明为 private.

这样可以防止客户程序员通过除由我们提供的方法之外的任意方式来创建一个实例,如果不把构造器声明为private,编译器就会自作聪明的自动同步一个默认的friendly构造器.这种实现方法是最常见的,也就是图1中结构的标准实现.

 

public class Singleton {  
  private static Singleton s; 
  private Singleton(){};
  /**
   * Class method to access the singleton instance of the class.
   */
  public static Singleton getInstance() {
    if (s == null)
      s = new Singleton();
    return s;
  }
}
// 测试类
class singletonTest {
  public static void main(String[] args) {
    Singleton s1 = Singleton.getInstance();
    Singleton s2 = Singleton.getInstance();
    if (s1==s2)
      System.out.println("s1 is the same instance with s2");
    else
      System.out.println("s1 is not the same instance with s2");
  }
}

singletonTest运行结果是:

s1 is the same instance with s2

这证明我们只创建了一个实例.

二. 以静态变量为标志实现 Singleton 在类中嵌入一个静态变量做为标志,每次都在进入构造器的时候进行检查.

问题在于构造器没有返回类型,如果确定创建一个实例成功与否.一个方法是调用一个函数来检查创建是否成功,然后简单的返回一个来自静态变量的值,但是这样做是不优雅的,而且容易发生错误.比较好的做法是创建一个当创建了一个以上的实例时可以抛出异常的类,这个类仅仅是调用父类方法,好处是用了自己命名的异常类型,错误信息更加清晰:

 

class SingletonException extends RuntimeException {
  public SingletonException(String s) {
    super(s);
  }
}
class Singleton {
  static boolean instance_flag = false; // true if 1 instance
  public Singleton() {
    if (instance_flag)
      throw new SingletonException("Only one instance allowed");
    else
      instance_flag = true; // set flag for 1 instance
  }
}
// 测试类
public class singletonTest {
  static public void main(String argv[]) {
    Singleton s1, s2;
    // create one incetance--this should always work
    System.out.println("Creating one instance");
    try {
      s1 = new Singleton();
    } catch (SingletonException e) {
      System.out.println(e.getMessage());
    }
    // try to create another spooler --should fail
    System.out.println("Creating two instance");
    try {
      s2 = new Singleton();
    } catch (SingletonException e) {
      System.out.println(e.getMessage());
    }
  }
}

singletonTest运行结果是:

Creating one instance

Creating two instance

Only one instance allowed

可以看出,第一个实例顺利创建,第二个实例创建实抛出了我们自定义的异常.

三. 用注册器机制来创建 Singleton 首先用集合中的Hashtable 和Enumeration来实现addItem(Object key, Object value),getItem(Object key), ,removeItem(Object key)等方法实现一个管理器,将key和value一一关联起来,客户程序员创建实例前首先用addItem方法进行注册,再用getItem方法获取实例.Hashtable中的key是唯一的,从而保证创建的实例是唯一的,具体实现限于篇幅不再细说,在Prototype模型的应用一文中我将会给出一个实现注册器的代码.用注册器机制来创建 Singleton模式的好处是易于管理,可以同时控制多个不同类型的Singleton 实例.

 




小结

  1. Singleton模式可以方便的进行扩充,产生指定数目的实例.
  2. 在The Design Patterns Java Companion 一书中曾提到过用静态类的方式来实现 Singleton模式,并指出java.lang.Math就是一个例子,这里我并不表示赞同,因为Math并不是一个真正的对象,我们只是直接调用Math类所包装的静态方法而已,根本就没有创建实例的过程,又从何说起只产生一个实例呢?这个问题我曾到Javaranch的论坛上发过帖子,所有回帖的人也都是对这一观点持否定态度.
  3. 在多线程的程序中,singleton可能会变的不可靠,可能会出现多个实例,解决的办法很简单,加个同步修饰符: public static synchronized Singleton getInstance(). 这样就保证了线程的安全性.
  4. 最后要说的是大家可能会看见一些其他实现Singleton模式的方法,因为模式在具体的应用时是灵活的,不是一成不变的,并没有一个固定的做法,但大都是上面几种方法的变形.
第四次工业革命如何重构产业逻辑:写给技术人的趋势推演 第四次工业革命正在以人工智能、大数据和新能源为核心重构全球产业逻辑。本文从历史规律切入,指出技术革命本质是生产力跃迁和产业链话语权的转移。当前AI基础设施竞赛已形成算力、数据、算法三大支柱,其中算力投资首超石油领域,绿色算力与新型架构成为关键。数据治理带来隐私计算等新技术约束,数据中心正向液冷技术和"东数西算"模式演进。技术人需构建三大竞争力:夯实分布式系统等底层能力、培养跨领域知识融合能力、善用约束条件驱动创新。这场变革将奖励那些深度理解技术本质并能快速适应的实践者。 阅读详情

相关推荐

J-LINK下载程序出现No Cortex-M Device found in JTAG chain…问题,最全7种解决方法

J-Link下载程序出现No Corect 等的问题的7种方法 后来编辑JLinkSettings.ini文件,找到"Device"项,将其更改Device="Cortex-M0+"

cjmsea的博客 5613

【从零开始学习JAVA | 第二十三篇】集合体系结构

JAVA中为我们提供了很多集合,这些集合都有自己很独特的特点,因此我们要学习所有的集合,但是在学习所有的集合之前,我们还是先为大家介绍一下JAVA的集合体系结构,这样有利于大家更好的理解整个JAVA集合框架。

fckbb的博客 1968

Word公式一键转MathType保姆级教程(附omml2mml.xsl报错终极解决方案)

本文提供Word公式一键转MathType的保姆级教程,重点解决常见的omml2mml.xsl报错问题。通过详细分析报错原因、官方解决方案实操步骤及转换后格式优化技巧,帮助用户高效完成公式转换,适用于科研论文和商业文档编辑。

weixin_30082367的博客 551

Java Collections singleton()方法与示例

集合类singleton()方法 (Collections Class singleton() method) singleton() method is available in java.util package. singleton()方法在java.util包中可用。 singleton() method is used to return an immutable set [i.e. ...

1万+

基恩士PLC编程避坑指南:局部变量@前缀的3个隐藏陷阱与实战解决方案

本文深入剖析了基恩士PLC编程中使用@前缀创建局部变量的三大隐藏陷阱,包括在线调试时的数据丢失、数据类型冲突以及子程序复用时的地址覆盖问题。针对每个陷阱,提供了预定义变量、强类型规范和基址参数传递等实战解决方案,帮助中高级工程师提升代码健壮性与可维护性。

weixin_29171087的博客 102

在实战中学AI-车流量统计项目-YOLOV11车辆检测-YOLOV11模型的部署

考虑实际落地中部署推理资源消耗,速度与模型精度之间的均衡,同时,车辆属于比较通用场景的目标检测,我们将YOLOV11作为最终的模型选择,目前官方开源的模型基于coco数据集训练,里面已经包含了车辆相关类别,经测试,在监控视角下效果基本可用,所以,在落地过程中,我们先用这个模型来打通部署链路,后面再逐步优化模型性能。在Nvidia的硬件下做部署,部署框架优先选择官方框架TensorRT,下面重点讲述如何用TensorRT部署YOLOV11模型。

Aleo_优快云的博客 2165

在Java中应用设计模式之Singleton

基本概念    ingleton 是一种创建性模型,它用来确保只产生一个实例,并提供一个访问它的全局访问点。正在装载数据……对一些类来说,保证只有一个实例是很重要的,比如有的时候,数据库连接或 Socket 连接要受到一定的限制,必须保持同一时间只能有一个连接的存在。    再举个例子,集合中的 set 中不能包含重复的元素,添加

meteorWJ's Home—Floating clound 845

利用 HTML5 与 SICF 打造 CRM WebClient UI 多附件上传 —— 从原型到生产的全流程揭秘

通过HTML5 标准 + SICF 服务 + BOL/GOS API的三位一体方案,我们无需修改 SAP 标准代码,就能让 CRM WebClient UI 获得现代化的多附件上传体验。浏览器负责多选与进度提示,SICF 负责安全中转,ABAP 负责权限校验与落库。你可以先在质量系统快速原型,再逐步完善权限、异常处理与 UI 细节。按照本文的方法落地,哪怕一次上传几百份文件,也能轻松搞定,真正把时间还给业务。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 333

Java单例模式Singleton

Singleton是一种创建性模型,它确保只产生一个实例,并提供一个访问它的全局访问点,对于有些类来说,确保只有一个实例是很重要的,比如有的时候数据库的连接、Socket连接要受到一定的限制,必须确保同一时间只有一个连接的存在。再举个例子,集合中的set中不能包含重复的元素,添加到set里的对象必须是唯一的,如果重复的添加到set,它只接受一个实例,JDK中正式运用了Singleton模式来实现s

liujiegood10136的专栏 586

【YOLOv8-pose姿态识别部署至RK3588:模型训练到RKNN落地,让人体姿态分析精度与边缘推理速度双突破】

本教程从YOLOv8-pose模型的姿态识别训练,到RK3588的边缘量化部署,为你打造了一套“高精度+高实时性+低成本”的人体姿态分析解决方案。无论是健身动作纠正、智能安防行为检测,还是工业人员姿态监控,这套技术都能直接复用——你只需替换数据集与业务逻辑,即可快速落地专属的边缘AI姿态识别系统。如果你在实践中遇到任何卡点,欢迎随时交流。记住,人体姿态识别的价值在于“关键点准、推理快、部署易”,而这三者的平衡,正是你通过本教程能掌握的核心能力。

FJN110的博客 328

无需Python环境!纯C#上位机+OpenCVSharp4+ONNX Runtime实现YOLOv8摄像头实时流检测,工业级稳定

摘要 工业自动化C#开发中,传统Python方案实现视觉检测功能存在环境依赖、内存泄漏和性能不稳定等问题。本文提出基于.NET 8+OpenCVSharp4+ONNX Runtime的纯C#方案,通过实际案例验证其优势: 零Python依赖,支持离线部署 内存稳定(380MB/72h),检测延迟<80ms 检测精度达漏检率<0.1%,误检率<0.5% 保留原有业务逻辑代码,3天完成适配 方案采用分层架构设计,支持多种硬件平台和操作系统,提供从模型导出到部署的全流程指导,为工业视觉检测提供高

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 196

[从零开始学习JAVA ] 集合体系结构

TreeMap是通过红黑树实现的。

2301_80615512的博客 1600

不会C# Winform用户界面设计?是因为没有掌握这些控件(建议收藏)

文章目录6.1 常用控件6.1.1 单选按钮(RadioButton)6.1.2 复选框(CheckBox)6.1.3 框架1. 面板控件Panel2. 分组框GroupBox3. TabControl控件6.1.4 应用实例6. 2 列表框和组合框6.2.1 列表框(ListBox)6.2.2 组合框(ComboBox )6.2.3 应用实例6.3 用户交互界面6.3.1 滚动条和进度条6.3.2 定时器6.3.3 菜单设计菜单设计概述MenuStrip和ContextMenuSt

智慧空间实验室 2919

在Java中应用设计模式--Singleton

在Java中应用设计模式--Singleton 作者:刘湛    来自:IBM   本文介绍了设计模式中 Singleton 的基本概念,对其功能和用途进行了简单的分析,列出了通常实现 Singleton 的几种方法,并

吃掉大象的蚂蚁的专栏 842

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Java 中应用设计模式 -- Singleton

基本概念 Singleton 是一种创建性模型,它用来确保只产生一个实例,并提供一个访问它的全局访问点.对一些类来说,保证只有一个实例是很重要的,比如有的时候,数据库连接或 Socket 连接要受到一定的限制,必须保持同一时间只能有一个连接的存在.再举个例子,集合中的 set 中不能包含重复的元素,添加到set里的对象必须是唯一的,如果重复的值添加到 set,它只接受一个实例.JDK中正式运

wuhao8989的专栏 454

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

上一篇: Java调用存储过程的2种方法
下一篇: SQL SERVER性能优化综述(很好的总结,不要错过哦)第1/3页
SpringJava
博客等级 码龄20年 8粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值