设计模式从入门到精通之(三)单例模式

news2025/1/6 19:38:39

单例模式:只留一份独特的存在

在现代软件设计中,有些对象是必须确保"独一无二"的,比如程序中的配置管理器、线程池、数据库连接等。如果允许这些对象被反复创建,不仅会浪费系统资源,还可能导致程序逻辑出错。今天我们要聊的单例模式,正是用来解决这些问题的。


1. 什么是单例模式?

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并且提供全局访问点来获取该实例。简单来说,单例模式就是全球通用的唯一代言人

在实际开发中,单例模式常用于:

  1. 配置管理:程序中的全局配置只需要一个实例。
  2. 资源共享:某些资源(如线程池、日志系统)必须全局共享。
  3. 控制实例数量:限制某些类的实例数量,避免资源浪费。

2. 用现实中的故事引出单例模式

想象你在一个学校任教。学校的公告栏是全校师生获取通知的唯一地方,所有的信息都必须通过公告栏发布。假如学校允许多个公告栏存在,那可能会导致混乱,比如不同公告栏上的信息不一致。

因此,学校必须确保公告栏唯一性,而且所有人都知道它的位置。这就是单例模式的思想:一个类只能有一个实例,而且这个实例对全局都是可见的。


3. 单例模式的代码实现

下面我们以公告栏为例,来实现单例模式。

3.1 饿汉式单例

饿汉式单例在类加载时就完成实例化,因此线程安全,但如果实例从未被使用,会浪费内存。

class BulletinBoard {
    // 1. 提前创建唯一实例
    private static final BulletinBoard instance = new BulletinBoard();

    // 2. 私有构造方法,防止外部实例化
    private BulletinBoard() {
        System.out.println("公告栏已初始化");
    }

    // 3. 提供全局访问点
    public static BulletinBoard getInstance() {
        return instance;
    }

    public void postMessage(String message) {
        System.out.println("公告:" + message);
    }
}

public class Main {
    public static void main(String[] args) {
        BulletinBoard board = BulletinBoard.getInstance();
        board.postMessage("明天学校停电,请提前做好准备。");
    }
}

运行结果:

公告栏已初始化
公告:明天学校停电,请提前做好准备。
3.2 懒汉式单例

懒汉式单例在第一次调用时创建实例,节省资源,但必须考虑线程安全问题。

class BulletinBoard {
    // 1. 声明静态变量,但不初始化
    private static BulletinBoard instance;

    // 2. 私有构造方法
    private BulletinBoard() {
        System.out.println("公告栏已初始化");
    }

    // 3. 提供线程安全的全局访问点
    public static synchronized BulletinBoard getInstance() {
        if (instance == null) {
            instance = new BulletinBoard();
        }
        return instance;
    }

    public void postMessage(String message) {
        System.out.println("公告:" + message);
    }
}
3.3 双重检查锁(推荐)

双重检查锁结合了饿汉式和懒汉式的优点,既保证了线程安全,又提升了性能。

class BulletinBoard {
    private static volatile BulletinBoard instance;

    private BulletinBoard() {
        System.out.println("公告栏已初始化");
    }

    public static BulletinBoard getInstance() {
        if (instance == null) {
            synchronized (BulletinBoard.class) {
                if (instance == null) {
                    instance = new BulletinBoard();
                }
            }
        }
        return instance;
    }

    public void postMessage(String message) {
        System.out.println("公告:" + message);
    }
}

4. 单例模式的优缺点

优点:

  1. 全局唯一性:确保一个类只有一个实例,节省资源。
  2. 全局访问:为程序提供统一的访问点,方便管理。
  3. 延迟初始化(懒汉式):提升性能,减少启动时的资源开销。

缺点:

  1. 不易扩展:由于单例模式强制只有一个实例,难以被继承或修改。
  2. 多线程问题:懒汉式实现需要小心处理线程安全。
  3. 隐藏依赖:过度使用单例可能让代码之间的依赖关系不清晰,增加维护难度。

5. 总结

单例模式看似简单,却是软件设计中的一颗"小而美"的明珠。在需要确保全局唯一性的时候,单例模式是非常高效的解决方案。但它也不是万能的,滥用单例可能导致代码难以测试和维护。

下一篇专栏中,我们将介绍一种和工厂模式密切相关的模式:建造者模式,看看如何一步步优雅地构建复杂对象。


思考问题:
在双重检查锁的实现中,为什么instance需要用volatile关键字修饰?如果省略,会产生什么问题?欢迎在评论区讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Golang的代码质量分析工具

Golang的代码质量分析工具 一、介绍 作为一种高效、简洁、可靠的编程语言,被越来越多的开发者所喜爱和采用。而随着项目规模的增长和团队人员的扩大,代码质量的管理变得尤为重要。为了保障代码的可维护性、健壮性和可扩展性,我们需要借助代码…

鸿蒙元服务 口袋管家(从0到1) ——准备工作

达到的效果图 如何创建元服务? 如下: 鸿蒙如何创建元服务-元服务是什么?和App的关系?(保姆级步骤)_鸿蒙元服务-CSDN博客 开始创建包 Bill 里面创建两个page页面 分别是 BillAddPage 和 BillIndexPag…

轻量型web组态软件

体验地址:http://www.hcy-soft.com 随着互联网、物联网技术的快速发展,BY组态基于多年研发积累和私有部署实践打磨、以及对业务场景的深入理解,推出了适用于物联网应用场景的轻量型web组态软件。 该产品采用 B/S 架构,提供 web …

Linux C/C++编程-获得套接字地址、主机名称和主机信息

【图书推荐】《Linux C与C一线开发实践(第2版)》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践(第2版)(Linux技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com…

SweetAlert2 - 漂亮可定制的 JavaScript 弹窗

https://sweetalert2.github.io/ https://github.com/sweetalert2/sweetalert2 安装: npm install sweetalert2封装: import Swal from sweetalert2/dist/sweetalert2.js import sweetalert2/src/sweetalert2.scss/*** * param {string} icon - ico…

Android布局layout的draw简洁clipPath实现圆角矩形布局,Kotlin

Android布局layout的draw简洁clipPath实现圆角矩形布局,Kotlin 通常,如果要把一个相对布局,FrameLayout,或者线性布局等这样的布局变成具有圆角或者圆形的布局,需要增加一个style,给它设置圆角,…

PHP如何删除数组中的特定值?

php 中删除数组特定值的方法有三种:unset():直接删除指定索引的值,但会保留数组索引结构和未删除元素,适合小数组。array_filter():根据自定义回调函数筛选数组元素,返回一个新数组,原数组不变&…

啤酒风味塑造的关键因素——麦汁煮沸

在探索啤酒酿造的工艺过程中,我们发现每一个细微的步骤都对最终的口感和风味产生着不可忽视的影响。今天,让我们深入探讨一个关键环节——麦汁煮沸,以及其中至关重要的概念“煮沸强度”。 何谓煮沸强度?它又如何左右麦汁的品质&a…

unity开发之shader 管道介质流动特效

效果 shader graph 如果出现下面的效果,那是因为你模型的问题,建模做贴图的时候没有设置好UV映射,只需重新设置下映射即可

JAVA学习笔记_JVM

文章目录 初识jvm内存结构程序计数器(寄存器) 栈问题辨析内存溢出 线程诊断本地方法栈Heap堆内存溢出内存诊断 方法区内存溢出常量池 stringTable直接内存垃圾回收 初识jvm JRE JVM 基础类库 JDK JRE 编译工具 JavaSE JDK IDE工具 JavaEE JDK 应用服务器 IDE工具 jvm是…

供需平台信息发布付费查看小程序系统开发方案

供需平台信息发布付费查看小程序系统主要是为了满足个人及企业用户的供需信息发布与匹配需求。 一、目标用户群体 个人用户:寻找兼职工作、二手物品交换、本地服务(如家政、维修)等。 小微企业:推广产品和服务,寻找合…

牛客网刷题 ——C语言初阶——OR76 两个整数二进制位不同个数

1. 牛客网题目:OR76 两个整数二进制位不同个数 牛客网OJ链接 描述: 输入两个整数,求两个整数二进制格式有多少个位不同 输入描述:两个整数 输出描述:二进制不同位的个数 示例1 输入:22 33 输出&#xff1a…

直播美颜SDK深度优化技术探索:低延迟与高画质的平衡之道

本篇文章,小编将从技术角度出发,探讨直播美颜SDK的优化方法,探索实现低延迟与高画质并存的解决方案。 一、低延迟的技术挑战与应对策略 直播的核心在于实时互动,任何超过100ms的延迟都会显著影响用户体验。而美颜处理由于涉及复…

链表算法篇——链接彼岸,流离节点的相遇之诗(下)

文章目录 前言第一章:重排链表1.1 题目链接:https://leetcode.cn/problems/reorder-list/description/1.2 题目分析:1.3 思路讲解:1.4 代码实现: 第二章:合并K个升序链表2.1 题目链接:https://l…

WebRTC的线程事件处理

1. 不同平台下处理事件的API: Linux系统下,处理事件的API是epoll或者select;Windows系统下,处理事件的API是WSAEventSelect,完全端口;Mac系统下,kqueue 2. WebRTC下的事件处理类: …

【Cocos TypeScript 零基础 4.1】

目录 背景滚动 背景滚动 创建一个 空节点 背景丟进去 ( 复制一个,再丢一次都行) 新建TS脚本 并绑定到 空节点 上 再对TS脚本进行编辑 export class TS2bg extends Component {property (Node) // 通过属性面板去赋值bg1:Node nullproperty (Node) bg2:Node nullprope…

利用 AI 高效生成思维导图的简单实用方法

#工作记录 适用于不支持直接生成思维导图的AI工具;适用于AI生成后不能再次编辑的思维导图。 在日常的学习、工作以及知识整理过程中,思维导图是一种非常实用的工具,能够帮助我们清晰地梳理思路、归纳要点。而借助 AI 的强大能力&#xff0c…

AfuseKt1.4.4 | 刮削视频播放器,支持阿里云盘和自动海报墙

AfuseKt是一款功能强大的安卓端在线视频播放器,广泛兼容多种平台如阿里云盘、Alist、WebDAV、Emby、Jellyfin等,同时也支持本地存储视频文件的播放。其特色功能包括自动抓取影片信息生成海报墙展示,充分利用设备硬件进行高清视频流畅播放&…

Linux下部署ElasticSearch集群

Elasticsearch7.17.8集群的搭建 节点host名称节点ip节点部署内容k8s-m192.168.40.142主节点 数据节点k8s-w1192.168.40.141主节点 数据节点k8s-w2192.168.40.140数据节点 一、准备安装环境 1.下载安装包 官网 www.elastic.co 下载所有版本地址 点击跳转 下载elasticsearch-7.…

covid-vaccine-availability-using-flask-server

使用烧瓶服务器获得 Covid 疫苗 原文:https://www . geesforgeks . org/co vid-疫苗-可用性-使用-烧瓶-服务器/ 在本文中,我们将使用 Flask Server 构建 Covid 疫苗可用性检查器。 我们都知道,整个世界都在遭受疫情病毒的折磨,唯一能帮助我们…