单例模式-C#

news/2024/8/26 14:44:28 标签: 单例模式, c#

在C#中实现单例模式,主要目的是确保一个类仅有一个实例,并提供一个全局访问点来获取这个实例。以下是一个简单的单例模式实现示例,它使用了一个私有静态变量来保存类的唯一实例,并提供了一个公有的静态方法来获取这个实例。此外,还使用了私有构造函数来防止通过new关键字在类的外部创建实例。

单例模式的优点:

    1. 单例模式可以保证一个类只有一个实例,减少内存开销,降低系统的复杂度,并加强系统的稳定性。
    1. 单例模式可以避免对资源的多重占用,保证系统的一致性。
    1. 单例模式可以全局访问点,可以提供一个访问点,使得外界可以直接访问该实例。
    1. 单例模式可以提供一个统一的访问点,简化调用,提高代码的可读性和可维护性。

单例模式的缺点:

    1. 单例模式一般没有接口,扩展困难。
    1. 单例模式违反了依赖倒置原则,一个模块应该依赖于抽象,而不是具体的实现。
    1. 单例模式对测试不利,难以对单例进行单元测试。
    1. 单例模式在多线程环境下需要进行线程同步,可能会导致性能问题。
    1. 单例模式在一些框架中使用单例模式,可能会导致系统的复杂性。
    1. 单例模式在一些语言中不容易实现,比如Java中不能通过反射创建对象。
    1. 单例模式在一些场景下会增加系统的复杂度,比如多线程的应用场景。
    1. 单例模式在一些框架中使用单例模式,可能会导致系统的复杂性。
    1. 单例模式在一些语言中不容易实现,比如Java中不能通过反射创建对象。
    1. 单例模式在一些场景下会增加系统的复杂度,比如多线程的应用场景。

懒汉式(线程不安全)

这是最基本的实现方式,但在多线程环境下可能会创建多个实例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingletonPattern
{
    /// <summary>
    /// 懒汉式(线程不安全)
    /// 这是最基本的实现方式,但在多线程环境下可能会创建多个实例。
    /// </summary>
    internal class Singleton_LazyNoSafety
    {
        // 私有静态变量,用于存储类的唯一实例
        private static Singleton_LazyNoSafety instance;

        // 私有构造函数,防止外部创建实例  
        private Singleton_LazyNoSafety() 
        {
            Console.WriteLine("单例模式:懒汉式(线程不安全)!");
        }

        // 公有静态方法,返回类的唯一实例  
        public static Singleton_LazyNoSafety GetInstance()
        {
            // 如果实例不存在,则创建实例
            if (instance == null)
            {
                instance = new Singleton_LazyNoSafety();
            }
            return instance;
        }
    }
}

懒汉式(线程安全)

通过在GetInstance方法上添加lock关键字来确保线程安全。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingletonPattern
{
    /// <summary>
    /// 懒汉式(线程安全)
    /// 通过在GetInstance方法上添加lock关键字来确保线程安全。
    /// </summary>
    public class Singleton_LazySafety
    {
        private static Singleton_LazySafety instance;

        /*
         * lock 关键字是用于同步代码块,确保在同一时间内只有一个线程可以执行该代码块。
         * lock 关键字通过锁定一个对象来工作,任何线程在尝试进入被 lock 保护的代码块之前,都必须先获得该对象的锁。
         * 如果一个线程已经获得了锁,其他线程就必须等待,直到锁被释放。当线程退出 lock 代码块时,无论是因为正常执行完毕还是由于异常退出,锁都会被自动释放。
         */
        private static readonly object lockObj = new object();
        private Singleton_LazySafety()
        {
            Console.WriteLine("单例模式:懒汉式(线程安全)!");
        }
        public static Singleton_LazySafety GetInstance()
        {
            lock (lockObj)
            {
                if (instance == null)
                {
                    instance = new Singleton_LazySafety();
                }
            }
            return instance;
        }
    }
}

饿汉式

这种方式基于类加载机制避免了多线程同步问题,但是在类装载时就完成实例化,没有达到Lazy Loading的效果。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingletonPattern
{
    /// <summary>
    /// 饿汉式
    /// 这种方式基于类加载机制避免了多线程同步问题,但是在类装载时就完成实例化,没有达到Lazy Loading的效果。
    /// </summary>
    public class Singleton_Hungry
    {
        // 私有静态变量,用于存储类的唯一实例
        private static Singleton_Hungry instance;

        // 私有构造函数,防止外部创建实例  
        public Singleton_Hungry()
        {
            Console.WriteLine("单例模式:饿汉式!");//在类被加载时就会创建实例对象,不会被打印到控制台
        }

        // 公有静态方法,返回类的唯一实例  
        public static Singleton_Hungry GetInstance() 
        { 
            return instance; 
        }
    }
}

双重检查锁定(Double-Checked Locking)

这种方式既保证了线程安全,又避免了每次调用GetInstance时都进行同步,从而提高了性能。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingletonPattern
{
    /// <summary>
    /// 双重检查锁定(Double-Checked Locking)
    /// 这种方式既保证了线程安全,又避免了每次调用GetInstance时都进行同步,从而提高了性能。
    /// </summary>
    public class Singleton_DoubleCheckedLocking
    {
        // 使用volatile关键字确保多线程环境下的可见性  
        private static volatile Singleton_DoubleCheckedLocking instance;
        private static readonly object lockObject = new object();
        private Singleton_DoubleCheckedLocking()
        {
            Console.WriteLine("单例模式:双重检查锁定!");
        }
        public static Singleton_DoubleCheckedLocking GetInstance()
        {
            // 第一次检查实例是否存在,如果不存在,才进入下面的同步块  
            if (instance == null)
            {
                lock (lockObject)
                {
                    // 第二次检查实例是否存在,防止多个线程都通过了第一次检查并创建实例  
                    if (instance==null)
                    {
                        instance = new Singleton_DoubleCheckedLocking();
                    }
                }
            }
            return instance;
        }
    }
}

.NET Framework 4.0及更高版本

请注意,在.NET Framework 4.0及更高版本中,由于System.Lazy的引入,实现单例模式变得更加简单和高效。Lazy类提供了一种延迟初始化的机制,它确保对象在其Value属性被访问之前不会被实例化。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingletonPattern
{
    /// <summary>
    /// 4.0后高版本
    /// 在.NET Framework 4.0及更高版本中,由于System.Lazy<T>的引入,实现单例模式变得更加简单和高效。
    /// Lazy<T>类提供了一种延迟初始化的机制,它确保对象在其Value属性被访问之前不会被实例化。
    /// </summary>
    internal class Singleton_HighVersion
    {
        // 使用Lazy<T>实现单例模式  
        private static readonly Lazy<Singleton_HighVersion> lazy = new Lazy<Singleton_HighVersion>(() => new Singleton_HighVersion());

        // 私有构造函数  
        private Singleton_HighVersion()
        {
            Console.WriteLine("单例模式:4.0后高版本!");
        }

        // 公有静态属性,返回类的唯一实例  
        public static Singleton_HighVersion Instance => lazy.Value;
    }
}

调用结果

using System;

namespace SingletonPattern
{
    internal class Program
    {
        static void Main(string[] args)
        {

            var instance_lazy1 = Singleton_LazyNoSafety.GetInstance();
            var instance_lazy2 = Singleton_LazyNoSafety.GetInstance();
            // 比较内存地址判断是否同一个实例  
            Console.WriteLine(ReferenceEquals(instance_lazy1, instance_lazy2)); // 输出: True 


            var instance_lazy3 = Singleton_LazySafety.GetInstance();
            var instance_lazy4 = Singleton_LazySafety.GetInstance();
            Console.WriteLine(ReferenceEquals(instance_lazy3, instance_lazy4)); 


            //在类被加载时就会创建实例对象
            var instance_hungry1 = Singleton_Hungry.GetInstance();
            var instance_hungry2 = Singleton_Hungry.GetInstance();
            Console.WriteLine(ReferenceEquals(instance_hungry1, instance_hungry2));


            var instance_double1 = Singleton_DoubleCheckedLocking.GetInstance();
            var instance_double2 = Singleton_DoubleCheckedLocking.GetInstance();
            Console.WriteLine(ReferenceEquals(instance_double1, instance_double2));

            var instance_high1 = Singleton_HighVersion.Instance;
            var instance_hagh2 = Singleton_HighVersion.Instance;
            Console.WriteLine(ReferenceEquals(instance_high1, instance_hagh2));
        }
    }
}


http://www.niftyadmin.cn/n/5558187.html

相关文章

Telegram Bot、小程序开发(三)Mini Apps小程序

文章目录 一、Telegram Mini Apps小程序二、小程序启动方式三、小程序开发小程序调试模式初始化小程序Keyboard Button Mini Apps 键盘按钮小程序【依赖具体用户信息场景,推荐】**Inline Button Mini Apps内联按钮小程序**initData 的自动传递使用内联菜单时候哪些参数会默认传…

构建未来智能边缘:4G定制化ARM边缘计算网关解决方案

在当今数字化转型的时代背景下&#xff0c;边缘计算正成为连接物理世界与数字世界的关键桥梁&#xff0c;为企业提供实时数据处理和决策能力。为了满足市场对高性能、灵活且可定制的边缘计算解决方案的需求&#xff0c;一款专为各类品牌量身定制的ARMxy边缘计算网关 产品亮点&…

E: Unable to locate package google-chrome-stable_current_amd64.deb

意思是我无法定位到google-chrome-stable_current_amd64.deb 我提前下载好了文件 我执行的命令为: apt install google-chrome-stable_current_amd64.deb 这个是先定位网络资源&#xff0c;然后现在安装。我是已经下载好了。 所以执行一下命令: apt install ./google-chro…

通过手机控制家用电器的一个程序的设计(一)

一、概述 设计一款安卓平台上的家庭智能控制软件&#xff0c;通过语音识别指令控制家用电器。该软件结合离线语音识别技术、红外线和WIFI通讯技术&#xff0c;实现对家电的智能控制&#xff0c;如开关机、调温度、调频道等操作。 二、主要功能模块 离线语音识别模块 功能&…

Web前端-Web开发CSS基础5-浮动

一. 基础 1. 设置<div>元素的宽为100像素&#xff0c;高也为100像素&#xff0c;并且向左悬浮&#xff1b; 2. 设置<div>元素的宽为100像素&#xff0c;高也为100像素&#xff0c;并且向右悬浮&#xff1b; 3. 设置<img>元素向左悬浮&#xff1b; 4. 设置<…

基于STM32的无人机控制系统:硬件选择与软件实现(内附资料)

无人机&#xff08;Unmanned Aerial Vehicle, UAV&#xff09;在现代应用中越来越广泛&#xff0c;从军事侦察到民用物流&#xff0c;无人机技术的发展不断推动着相关硬件和软件的进步。STM32系列微控制器以其高性能、低功耗和丰富的外设接口&#xff0c;成为无人机控制系统的理…

第一阶段面试题总结

1. 线程和进程的概念&#xff0c;区别、以及什么时候用线程什么时候用进程 1.1 线程概念 线程是进程中的一个执行单元&#xff0c;一个进程可以包含多个线程 线程是一个轻量级的进程 线程是CPU任务调度的最小单元 1.2 进程概念 进程是一个程序的运行实例&#xff0c;它包含了…

【乐吾乐2D可视化组态编辑器】消息

消息 乐吾乐2D可视化组态编辑器demo&#xff1a;https://2d.le5le.com/ 监听消息 const fn (event, data) > {}; meta2d.on(event, fn);// 监听全部消息 meta2d.on(*, fn);// 取消监听 meta2d.off(event, fn); meta2d.off(*, fn); Copy 系统消息 event&#xff08;…