当前位置: 首页 > news >正文

设计模式-创建型模式-单例模式

0 引言

创建型模式(Creational Pattern)关注对象的创建过程,是一类最常用的设计模式,每个创建型模式都通过采用不同的解决方案来回答3个问题:创建什么(What),由谁创建(Who)和何时创建(When)。

 1 单例模式

单例模式有3个要点:①某个类只能有一个实例;②它必须自行创建这个实例;③它必须自行向整个系统提供这个实例。

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。[DP]

1.1 饿汉单例模式

 在类加载的时候就已经实例化,并且创建单例对象,以后直接使用即可。这种模式下,类加载较慢,但获取对象的速度快,且线程安全。

public class HungrySingleton {// 在类加载时就已经完成了实例的初始化private static final HungrySingleton instance = new HungrySingleton();// 构造器私有,防止外部通过new关键字创建对象private HungrySingleton() {}// 提供全局访问点public static HungrySingleton getInstance() {return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of HungrySingleton.");}public static void main(String[] args) {// 获取单例对象HungrySingleton instance1 = HungrySingleton.getInstance();HungrySingleton instance2 = HungrySingleton.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}

1.2 懒汉单例模式

一开始不会实例化,什么时候用就什么时候进行实例化。这种模式下,类加载较快,但获取对象的速度稍慢,且可能在多线程情况下出现线程安全问题。

 存在线程安全问题,

public class LazySingleton {// 私有静态实例,初始化为nullprivate static LazySingleton instance = null;// 私有构造方法,防止外部通过new关键字创建对象private LazySingleton() {}// 提供全局访问点public static  LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of LazySingleton.");}public static void main(String[] args) {// 获取单例对象LazySingleton instance1 = LazySingleton.getInstance();// 调用实例方法instance1.showMessage();}
}

加锁,

public class LazySingleton {// 私有静态实例,初始化为nullprivate static LazySingleton instance = null;// 私有构造方法,防止外部通过new关键字创建对象private LazySingleton() {}// 同步方法,提供全局访问点public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of LazySingleton.");}public static void main(String[] args) {// 获取单例对象LazySingleton instance1 = LazySingleton.getInstance();LazySingleton instance2 = LazySingleton.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}

然而,同步方法会导致性能下降,因为每次调用getInstance()方法时都需要进行同步。为了解决这个问题,可以使用双重校验锁(Double-Checked Locking,DCL)来实现更高效的懒汉单例模式:现在这样,我们不用让线程每次都加锁,而只是在实例未被创建的时候再加锁处理。同时也能保证多线程的安全。这种做法被称为Double-Check Locking(双重锁定)。

public class LazySingletonWithDCL {// volatile关键字确保instance在多线程环境下被正确初始化private static volatile LazySingletonWithDCL instance = null;// 私有构造方法,防止外部通过new关键字创建对象private LazySingletonWithDCL() {}// 提供全局访问点public static LazySingletonWithDCL getInstance() {if (instance == null) {// 第一次检查synchronized (LazySingletonWithDCL.class) {if (instance == null) {// 第二次检查instance = new LazySingletonWithDCL();}}}return instance;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of LazySingletonWithDCL.");}public static void main(String[] args) {// 获取单例对象LazySingletonWithDCL instance1 = LazySingletonWithDCL.getInstance();LazySingletonWithDCL instance2 = LazySingletonWithDCL.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}

使用内部静态类来实现单例模式,这种方式的特点是利用了类加载机制来保证初始化实例时只有一个实例被创建,并且由于JVM的类加载机制,这种方式是线程安全的。只适合java。

public class Singleton {// 私有构造方法,防止外部通过new关键字创建对象private Singleton() {}// 静态内部类,持有单例对象private static class SingletonHolder {// 静态初始化器,由JVM保证线程安全private static final Singleton INSTANCE = new Singleton();}// 提供全局访问点public static Singleton getInstance() {return SingletonHolder.INSTANCE;}// 如果需要,可以添加其他方法或属性public void showMessage() {System.out.println("This is an instance of Singleton.");}public static void main(String[] args) {// 获取单例对象Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();// 输出实例,验证是否为同一个对象System.out.println(instance1);System.out.println(instance2);// 验证是否为同一个对象的引用System.out.println(instance1 == instance2);// 调用实例方法instance1.showMessage();}
}

相关文章:

设计模式-创建型模式-单例模式

0 引言 创建型模式(Creational Pattern)关注对象的创建过程,是一类最常用的设计模式,每个创建型模式都通过采用不同的解决方案来回答3个问题:创建什么(What),由谁创建(W…...

备战蓝桥杯—— 双指针技巧巧答链表1

对于单链表相关的问题,双指针技巧是一种非常广泛且有效的解决方法。以下是一些常见问题以及使用双指针技巧解决: 合并两个有序链表: 使用两个指针分别指向两个链表的头部,逐一比较节点的值,将较小的节点链接到结果链表…...

微信小程序返回上一级页面并自动刷新数据

文章目录 前言一、获取小程序栈二、生命周期触发总结 前言 界面由A到B,在由B返回A,触发刷新动作 一、获取小程序栈 界面A代码 shuaxin(){//此处可进行接口请求从而实现更新数据的效果console.log("刷新本页面数据啦")},界面B代码 // 返回触…...

Spring⼯⼚创建复杂对象

文章目录 5. Spring⼯⼚创建复杂对象5.1 什么是复杂对象5.2 Spring⼯⼚创建复杂对象的3种⽅式5.2.1 FactoryBean 接口5.2.2 实例⼯⼚5.2.3 静态工厂 5.3 Spring 工厂的总结 6. 控制Spring⼯⼚创建对象的次数6.1 如何控制简单对象的创建次数6.2 如何控制复杂对象的创建次数6.3 为…...

Top-N 泛型工具类

一、代码实现 通过封装 PriorityQueue 实现&#xff0c;PriorityQueue 本质上是完全二叉树实现的小根堆&#xff08;相对来说&#xff0c;如果比较器反向比较则是大根堆&#xff09;。 public class TopNUtil<E extends Comparable<E>> {private final PriorityQ…...

Java 后端面试指南

面试指南 TMD&#xff0c;一个后端为什么要了解那么多的知识&#xff0c;真是服了。啥啥都得了解 MySQL MySQL索引可能在以下几种情况下失效&#xff1a; 不遵循最左匹配原则&#xff1a;在联合索引中&#xff0c;如果没有使用索引的最左前缀&#xff0c;即查询条件中没有包含…...

142.环形链表 ||

给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整…...

Nacos、Eureka、Zookeeper注册中心的区别

Nacos、Eureka和Zookeeper都是常用的注册中心&#xff0c;它们在功能和实现方式上存在一些不同。 Nacos除了作为注册中心外&#xff0c;还提供了配置管理、服务发现和事件通知等功能。Nacos默认情况下采用AP架构保证服务可用性&#xff0c;CP架构底层采用Raft协议保证数据的一…...

CSS重点知识整理1

目录 1 平面位移 1.1 基本使用 1.2 单独方向的位移 1.3 使用平面位移实现绝对位置居中 2 平面旋转 2.1 基本使用 2.2 圆点转换 2.3 多重转换 3 平面缩放 3.1 基本使用 3.2 渐变的使用 4 空间转换 4.1 空间位移 4.1.1 基本使用 4.1.2 透视 4.2 空间旋转 4.3 立…...

【Langchain多Agent实践】一个有推销功能的旅游聊天机器人

【LangchainStreamlit】旅游聊天机器人_langchain streamlit-CSDN博客 视频讲解地址&#xff1a;【Langchain Agent】带推销功能的旅游聊天机器人_哔哩哔哩_bilibili 体验地址&#xff1a; http://101.33.225.241:8503/ github地址&#xff1a;GitHub - jerry1900/langcha…...

算法学习(十二)并查集

并查集 1. 概念 并查集主要用于解决一些 元素分组 问题&#xff0c;通过以下操作管理一系列不相交的集合&#xff1a; 合并&#xff08;Union&#xff09;&#xff1a;把两个不相交的集合合并成一个集合 查询&#xff08;Find&#xff09;&#xff1a;查询两个元素是否在同一…...

TensorRT及CUDA自学笔记003 NVCC及其命令行参数

TensorRT及CUDA自学笔记003 NVCC及其命令行参数 各位大佬&#xff0c;这是我的自学笔记&#xff0c;如有错误请指正&#xff0c;也欢迎在评论区学习交流&#xff0c;谢谢&#xff01; NVCC是一种编译器&#xff0c;基于一些命令行参数可以将使用PTX或C语言编写的代码编译成可…...

数据库管理-第154期 Oracle Vector DB AI-06(20240223)

数据库管理154期 2024-02-23 数据库管理-第154期 Oracle Vector DB & AI-06&#xff08;20240223&#xff09;1 环境准备创建表空间及用户TNSNAME配置 2 Oracle Vector的DML操作创建示例表插入基础数据DML操作UPDATE操作DELETE操作 3 多Vector列表4 固定维度的向量操作5 不…...

解决uni-app vue3 nvue中使用pinia页面空白问题

main.js中&#xff0c;最关键的就是Pinia要return出去的问题&#xff0c;至于原因嘛! 很忙啊&#xff0c;先用着吧 import App from ./App import * as Pinia from pinia import { createSSRApp } from vue export function createApp() {const app createSSRApp(App);app.us…...

不用加减乘除做加法

1.题目&#xff1a; 写一个函数&#xff0c;求两个整数之和&#xff0c;要求在函数体内不得使用、-、*、/四则运算符号。 数据范围&#xff1a;两个数都满足 −10≤&#xfffd;≤1000−10≤n≤1000 进阶&#xff1a;空间复杂度 &#xfffd;(1)O(1)&#xff0c;时间复杂度 &am…...

旅游组团自驾游拼团系统 微信小程序python+java+node.js+php

随着社会的发展&#xff0c;旅游业已成为全球经济中发展势头最强劲和规模最大的产业之一。为方便驴友出行&#xff0c;寻找旅游伙伴&#xff0c;更好的规划旅游计划&#xff0c;开发一款自驾游拼团小程序&#xff0c;通过微信小程序发起自驾游拼团&#xff0c;吸收有车或无车驴…...

LeetCode 第41天 | 背包问题 二维数组 一维数组 416.分割等和子集 动态规划

46. 携带研究材料&#xff08;第六期模拟笔试&#xff09; 题目描述 小明是一位科学家&#xff0c;他需要参加一场重要的国际科学大会&#xff0c;以展示自己的最新研究成果。他需要带一些研究材料&#xff0c;但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实…...

Ubuntu20.04和Windows11下配置StarCraft II环境

1.Ubuntu20.04 根据下面这篇博客就可以顺利安装&#xff1a; 强化学习实战(九) Linux下配置星际争霸Ⅱ环境https://blog.csdn.net/weixin_39059031/article/details/117247635?spm1001.2014.3001.5506 Ubuntu下显示游戏界面目前还没有解决掉。 大家可以根据以下链接看看能…...

【NCom】:通过高温气相合成调节Pt-CeO2相互作用以提高晶格氧的还原性

摘要&#xff1a;在这项工作中&#xff0c;我们比较了通过两种方法制备的 Pt 单原子催化剂&#xff08;SAC&#xff09;的 CO 氧化性能&#xff1a;&#xff08;1&#xff09;传统的湿化学合成&#xff08;强静电吸附strong electrostatic adsorption–SEA&#xff09;&#xf…...

git 将一个分支的提交移动到另一个分支

假设想把分支A上的最后一部分commit移动到分支B之上&#xff1a; 首先切到分支B git checkout B然后执行如下指令,commit id 为A分支上&#xff0c;需要移动的那些提交 git cherry-pick <commit id> &#xff08; <commit id> 可多个&#xff09;中途可能遇到一些…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...

Vue3 PC端 UI组件库我更推荐Naive UI

一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用&#xff0c;前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率&#xff0c;还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库&#xff08;Naive UI、Element …...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...