C# 创建型设计模式之----单例模式

news/2024/10/28 13:39:24/

设计模式相信很多人在大学都有学过,当时学的时候肯定都学懂了的但在后来的程序开发中却很少会用到,好像其实际意义并不大。下面对其的简单说明希望能对大家的实际开发有所帮助和理解,当然这也仅是我的个人见解。用做自己的备忘录功能。

1、单例模式基本介绍

单例模式是一种确保一个类只有一个实例的设计模式

适用于需要频繁实例化然后销毁的对象,创建对象消耗资源过多,但又经常用到的对象。或者全局有且仅能有一个实例化的对象。其本质就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个

  • 特性和功能:确保一个类只有一个实例,并提供一个全局访问点。
  • 使用环境:当类只需要一个实例,且易于访问,且实例应在整个应用程序中共享时。
  • 注意事项:需要注意线程安全问题。
  • 优点:可以确保一个类只有一个实例,减少了内存开销。
  • 缺点:没有接口,扩展困难。

2、适用场景(部分)

2.1、 要求生成唯一序列号的环境;

比如记录网站实时登录人数,或者消息报文的编号。

2.2、在整个项目中需要一个共享访问点或共享数据:

例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;

2.3、创建一个对象需要消耗的资源过多:

如要访问IO和数据库等资源;

2.4、日志系统:

在应用程序中,通常只需要一个日志系统,以避免在多个地方创建多个日志对象。这一般是由于共享的日志文件一直处于打开状态,所以只能有一个实例去操作,否则内容不好追加也有可能造成资源占用加剧资源消耗。

2.5、数据库连接池(长连接场景):

在应用程序中,数据库连接池是一个非常重要的资源,单例模式可以确保在应用程序中只有一个数据库连接池实例,避免资源浪费。主要是节省打开或者关闭数据库连接所引起的效率损耗,因为何用单例模式来维护,就可以大大降低这种损耗。

2.6、配置文件管理器:

在应用程序中,通常只需要一个配置文件管理器来管理应用程序的配置文件,单例模式可以确保在整个应用程序中只有一个配置文件管理器实例。这个是由于配置文件是共享的资源。

2.7、缓存系统:

在应用程序中,缓存系统是一个重要的组件,单例模式可以确保在整个应用程序中只有一个缓存实例,以提高应用程序的性能。

3、创建方式:

单例模式其结构主要分为三部分:

        私有化构造函数:防止外部直接实例化对象。

        私有静态成员变量:用于保存唯一的实例。

        公有静态方法:提供获取该实例的唯一访问点。

单例模式分为懒汉式和饿汉式

3.1 懒汉式:

类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建。

线程安全(双重检查锁)的懒汉式示例(对于lock不了解的照着用就行):

双重检查的意义:

要实现线程安全其实只用使用lock给静态全局变量加锁即可,这样多个线程同时访问会排队等待。但是当第一个线程进入锁后就已经实例化对象了,后续的线程就算排队进入了也会因为对象已经不为null直接跳出程序,这样看来后面的线程排队进入锁内其实啥事没干就出去了,这就会造成资源的浪费,故此在锁的外面再判断静态变量是否为空这样仅第一个线程需要进入锁内去实例化对象,后续线程可直接返回对象即可。

public class Singleton{//定义一个私有的静态全局变量来保存该类的唯一实例private static Singleton singleton;//线程锁private static readonly object _Object = new object();/// <summary>/// 私有构造函数/// </summary>private Singleton(){//必须是私有的构造函数,防止外部通过new来创建该类的实例。//想要使用该类只能通过唯一访问点GetInstance()。}/// <summary>/// 全局访问点/// 设置为静态方法则可在外边无需创建该类的实例就可调用该方法,当然你也可以使用属性作为全局访问点/// </summary>/// <returns></returns>public static Singleton GetInstance(){if (singleton == null)//第一重{lock (_Object){if (singleton == null)//第二重{singleton = new Singleton();}}}return singleton;}}

使用方法:Singleton singletonOne = Singleton.GetInstance();

全局访问点除了使用方法以外还可使用属性进行调用

public class Singleton
{//静态变量private static Singleton _instance;//锁private static readonly object _lock = new();//私有构造函数private Singleton(){}//外部访问属性public static Singleton Instance{get{//保证效率,实例化后不再进入lock块if (_instance == null){//确保线程安全lock (_lock){if (_instance == null){_instance = new Singleton();}}}//已经被实例化直接返回return _instance;}}}

 使用方法:Singleton.Instance;

3.2 饿汉式:

类加载就会导致该单实例对象被创建。

在c#中使用静态初始化时无需显示地编写线程安全代码,C# 与 CLR 会自动解决前面懒汉式单例类的多线程同步问题。

public class Singleton
{// 私有静态成员readonly private static readonly Singleton instance = new Singleton();// 私有构造函数,防止外部直接实例化private Singleton() {}// 公有静态属性,提供访问单例实例的唯一访问点public static Singleton Instance{get{return instance;}}
}

到此想必你也看出来懒汉式和饿汉式的区别了吧,说简单点就是懒汉式的实例化是再外部接口里的,饿汉式的实例化是直接实例化的。

3.3 Lazy方式

当然除了上面两种还有一种使用C#的Lazy来实现

public class Singleton
{//第一个参数是一个工厂方法,返回一个T实例且没有形参;第二个参数true代表需要保证线程安全,false表示不需要线程安全private static readonly Lazy<Singleton> _instance = new Lazy<Singleton>(() => new Singleton(),true);public static Singleton Instance { get => _instance.Value; }private Singleton(){}
}

到此就结束了,上面三种方式都是线程安全的可放心使用,至于不安全的写法相比也没人需要吧。。


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

相关文章

《手写Spring渐进式源码实践》实践笔记(第十一章 AOP-基于JDK、Cglib实现对象动态代理)

文章目录 第十一章 基于JDK、Cglib实现对象动态代理背景目标设计实现代码结构类图代理案例解析案例代码运行结果拆解案例 实现步骤 测试事先准备自定义拦截方法测试用例测试结果&#xff1a; 总结 第十一章 基于JDK、Cglib实现对象动态代理 背景 到本章节我们将要从 IOC 的实现…

《创新:不灭的火炬》学习笔记

1.毛利率和研发强度用于刻画价值链和研发链。 2.三大重点领域&#xff1a;数字经济&#xff08;美国高研发投入占据产业链高毛利环节&#xff09;&#xff0c;绿色经济&#xff08;中国研发投入有领先地位&#xff09;&#xff0c;生物经济&#xff08;欧美不可替代较强&#…

基于阿里云服务的移动应用日志管理方案—日志的上传、下载、存档等

前言 如题&#xff0c;基于阿里云服务&#xff08;ECS、OSS&#xff09;实现 APP 的用户日志上传以及日志下载的功能&#xff0c;提高用户反馈问题到研发去分析、定位、解决问题的整个工作流的效率。 术语 ECS: 云服务器ECS&#xff08;Elastic Compute Service&#xff09;…

10.23Python_Matplotlib_‘backend_interagg‘ has no attribute

问题引入&#xff1a; 问题&#xff1a; import matplotlib.pyplot as plt import numpy as np# 创建数据 x np.linspace(0, 10, 100) y1 np.sin(x) y2 np.cos(x) y3 np.tan(x)# 创建图形 fig plt.figure(figsize(12, 4))# 第一个子图 ax1 fig.add_subplot(1, 3, 1) ax…

【深搜算法】(第四篇)

目录 求根节点到叶节点数字之和&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 ⼆叉树剪枝&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 求根节点到叶节点数字之和&#xff08;medium&#xff09; 题目解析 1.题目链接&#xff1…

【WiFi7】 支持wifi7的手机

数据来源 Smartphones with WiFi 7 - list of all latest phones 2024 Motorola Moto X50 Ultra 6.7" 1220x2712 Snapdragon 8s Gen 3 16GB RAM 1024 GB 4500 mAh a/b/g/n/ac/6e/7 Sony Xperia 1 VI 6.5" 1080x2340 Snapdragon 8 Gen 3 12GB RAM 512 G…

【IC每日一题】

IC每日一题 1 代码题&#xff1a;异步复位&#xff0c;同步释放2 八股题&#xff1a;同步复位VS异步复位 初步打算新开一个系列会包括&#xff1a;一个代码题 一个基本知识题&#xff1b; 1 代码题&#xff1a;异步复位&#xff0c;同步释放 题目&#xff1a;使用verilog来设…

WebSocket 连接频繁断开的问题及解决方案

文章目录 WebSocket 连接频繁断开的问题及解决方案1. 引言2. 什么是 WebSocket&#xff1f;2.1 WebSocket 的优势2.2 WebSocket 的工作原理 3. WebSocket 连接频繁断开的常见原因3.1 服务器端问题3.1.1 服务器负载过高3.1.2 服务器配置不当3.1.3 超时设置 3.2 网络问题3.2.1 网…