单例模式的实现

news/2024/11/9 17:08:54/

先上示例

public class DeviceManager
{private readonly Dictionary<string, Device> _devices;private DeviceManager(){_devices = new Dictionary<string, Device>();}public static DeviceManager Instance { get; } = new DeviceManager();    // { get; } 只读,外部不可对Instance做修改//也可能不叫Instance , Shared ,Defaultpublic void AddDevice(Device device){if (device == null){throw new ArgumentNullException(nameof(device));    //nameof(device)获取变量名}if (_devices.ContainsKey(device.Name)){throw new ArgumentException("Device with the same name already exists.");}lock (_devices){_devices.Add(device.Name, device);}}public Device GetDevice(string name){if (name == null){throw new ArgumentNullException(nameof(name));}lock (_devices){_devices.TryGetValue(name, out var device);return device;}           }
}public class Device
{public string Name { get; internal set; }
}

代码调用

try
{DeviceManager.Instance.AddDevice(new Device { Name = "Device1" });var device = DeviceManager.Instance.GetDevice("Device1");Console.WriteLine(device.Name) ;Console.ReadKey();
}
catch (Exception ex)
{Console.WriteLine(ex.Message);
}

为什么要使用单例模式

    线程安全:在需要多线程环境下使用时,单例模式可以提供线程安全的访问控件。DeviceManager.Instance 是静态属性,有.Net Framework在程序加载时进行初始化,确保了多线程下的安全范围

    为什么会有线程安全问题:在多线程环境中,需确保数据和资源的安全访问,因为多个线程同时操作共享的数据可能会导致数据不一致的行为。

    为什么单例能保证线程安全:在下面例子中,静态属性DeviceManage.Instance 是在 程序加载时 初始化的,且只会 初始化一次,确保软件整个生命周期内,只有一个 DeviceManage.Instance 实例存在

    保证线程安全的方式:
        1.静态属性的初始化是由 CLR(Common Language Runtime) 保证的, CLR会在第一次访问静态属性时进行初始化, 并且会阻止多个线程同时进行初始化操作,避免竞态条件。
        2.互斥访问:DeviceManger 类的方法,字段和构造器都是私有的,因此外部无法直接修改_device字典,内部方法又是可控的(可以通过Lock),这样可以避免多个线程同时修改_Device 引起并发问题
        3.线程同步:如果 DeviceManager 类中存在需要多线程访问和修改的共享资源,可以使用线程同步机制来确保安全访问,比如使用 lock 关键字或者 Monitor 类来保护关键代码段,防止多线程竞争条件的发生。
 
此外单例模式的优点:全局访问、资源共享、避免重复实例化、单一职责

适用单例的场景
    1.全局状态(配置文件读取,系统设置)或配置
    2.资源管理 (数据库连接池,文件系统管理器,线程池) 
    3.日志记录 日志记录器
    4.缓存管理 缓存系统通常需要统一管理,以便在不同部分的应用程序中共享数据。
    5.设备连接管理 管理外部设备(打印机,传感器)或网络连接时,需要确保系统中只有一个控制器实例来管理设备的通讯或连接
    6.服务定位器

不适用单例的场景
    1. 多线程问题: 当单例模式未正确实现时
    2. 测试和依赖注入: 需了解**
    3. 单例可能会增加耦合性


http://www.ppmy.cn/news/1515817.html

相关文章

Java | Leetcode Java题解之第355题设计推特

题目&#xff1a; 题解&#xff1a; class Twitter {private class Node {// 哈希表存储关注人的 IdSet<Integer> followee;// 用链表存储 tweetIdLinkedList<Integer> tweet;Node() {followee new HashSet<Integer>();tweet new LinkedList<Integer&g…

UneMeta创始人讲述自己在Web3+IP领域创业的心路历程

昨日&#xff0c;UneMeta创始人&#xff0c;Ann_tyrion在X分享了一篇推文&#xff0c;分享了自己在探索Web3与IP产业结合过程中的心路历程&#xff0c;她并没有像很多项目方那样一味的讲述宏大的叙事&#xff0c;而是字里行间透露出对这个行业的探索和不断给自己充实信念&#…

go设计模式——单例模式

概念 单例是一种创建型设计模式&#xff0c;它确保一个类在整个程序运行期间只有一个实例&#xff0c;并提供一个全局访问点来使用该实例。虽然单例模式在某些情况下非常有用&#xff0c;例如管理全局配置、日志记录或资源共享&#xff0c;但它也带来了与全局变量相似的问题。…

高并发业务下的无损技术方案设计

0 前言 秒杀&#xff0c;既有需求真实且迫切的用户&#xff0c;也有试图牟利的黄牛。系统挑战&#xff0c;就是相较于以往千倍万倍的用户规模&#xff0c;可能是真人可能是机器人&#xff0c;在同一瞬间对系统发起冲击&#xff0c;需要海量的计算资源才能支撑。 秒杀系统的设计…

MVC 参考手册

MVC 参考手册 1. 引言 MVC(Model-View-Controller)是一种广泛使用的软件架构模式,它将应用程序的逻辑分为三个相互关联的组件:模型(Model)、视图(View)和控制器(Controller)。这种模式最早在20世纪70年代被提出,用于Smalltalk编程语言中,后来被广泛采用于各种编程…

Elasticsearch安装 Kibana安装

安装Elasticsearch 一、拉取镜像或者上传 docker pull Elasticsearch 二、将上传的镜像导入(在仓库拉取的这一步跳过) docker load -i es.tar docker load -i 三、创建容器 1.Elasticsearch 注意修改到自己的网络&#xff08;第八行&#xff09; docker run -d \--nam…

【springboot系列】springboot的启动原理,springboot应用是如何启动的

【springboot系列】springboot的启动原理&#xff0c;springboot应用是如何启动的 Spring Boot的启动原理是一个复杂而精妙的流程&#xff0c;它负责加载配置、初始化应用上下文、自动配置和启动内嵌服务器等任务。以下是Spring Boot启动原理的详细解释&#xff1a; 1. 加载主…

一文入门:正则表达式基础

正则表达式简介 正则表达式&#xff08;Regular Expression&#xff0c;简称regex或RE&#xff09;是一种用于匹配字符串中字符组合的模式。它广泛应用于编程语言、文本编辑器和各种工具中&#xff0c;用于执行复杂的字符串搜索和替换任务。 为什么使用正则表达式&#xff1f…