c#中单例类与静态类的区别以及使用场景

作者:webmote33 时间:2021-07-21 17:06:30 

目录
  • 前言

  • 1.设计模式:单例模式

    • 1.1 使用时分配,

    • 1.2 声明时实例化

    • 1.3 双检锁

    • 1.4 .net 特性保证的线程安全

    • 1.5 使用DI依赖注入时的实现

  • 2. 单例类和静态类的比较

    • 3.使用场景

      • 总结

        前言

        哈哈,我来了,我又来了,在这年关将至的时候,趁有时间,就多学习和温习点老的知识。我们在.net core开发中,会经常使用注入来注入一个单例类,而在没有注入的时候,大部分情况会自己实现一个单例类,或者更简单的就是实现一个静态类。而常常在使用中,都能完成特定的目的,然而它们间的区别是什么呢?

        1.设计模式:单例模式

        单例模式:属于设计模式中创建类型的模式,通过单例模式的方法创建的类,在当前程序中只有一个实例,当然可以实现为线程安全的单例。

        这里简单复习下创建代码:

        1.1 使用时分配,

        使用时实例化,多线程应用时,使用不当会有线程安全问题。


        public class SingletonA
        {
         //私有成员,使用时分配内存
         private static SingletonA _instance = null;
         //私有构造,杜绝直接new类
         private SingletonA() { }

        //获取实例
         public static SingletonA GetInstance ()
         {

        if (_instance == null)
          {
           _instance = new SingletonA();
          }
          return _instance;
         }
        }

        1.2 声明时实例化

        声明实例时实例化,多线程应用时,使用不当会有线程安全问题。


        public class SingletonB
        {
         //私有静态成员,声明类实例时,分配
         private static readonly SingletonB _instance = new SingletonB();
         //私有构造,杜绝直接new类
         private SingletonB() { }
         public static SingletonB GetInstance()
         {  
          return _instance;
         }
        }

        1.3 双检锁

        推荐这个,经典的线程安全单例实现


        public class SingletonD
        {
         private static SingletonD _instance = null;
         private static readonly object _lockObject = new object();
         private SingletonD() { }
         public static SingletonD GetInstance()
         {
          if (_instance == null)
          {
           lock (_lockObject)
           {
            if (_instance == null)
             _instance = new SingletonD();
           }
          }
          return _instance;
         }
        }

        1.4 .net 特性保证的线程安全

        最精简版


        public sealed class SingletonC
        {
         private SingletonC() { }
         public static readonly SingletonC Instance = new SingletonC();
        }

        1.5 使用DI依赖注入时的实现


        //FileLogger只需要定义成一般的类即可,无需按照单例模式进行实现,当然也不能是静态类。

        public void ConfigureServices(IServiceCollection services)
        {
         services.AddControllersWithViews();
         services.AddSingleton<ILogger, FileLogger>();
        }

        2. 单例类和静态类的比较

        我们基于以下几个要点进行比较

        • 是否支持依赖注入

        • 内存管理是怎样的

        • 可扩展性

        • 可测试性

        静态类形如:


        public static class StaticExample
        {
         private static readonly object lockObj = new object();
         public static void Log(string message)
         {
          //Write code here to log data.
         }
        }
        特性比较静态类单例类
        是否支持依赖注入否,编译时提示静态类型不能作为类型参数支持
        内存管理是怎样的静态类存储在托管堆的high frequency heap,仅当应用程序卸载时,才释放内存单例类的单个实例是静态的,因此也保存在high frequency heap,当应用程序卸载时,才释放内存。但是,与只能具有静态对象的静态类不同,单例类可以同时具有静态和非静态对象。因此,从内存管理的角度来看,当您使用单例类时,可以利用垃圾回收管理对象。
        可扩展性您不能继承静态类并覆盖其方法 ;静态类不能具有扩展方法单例类通常包含一个私有构造函数,并标记为已密封,以指示它既不能实例化也不能继承;因此,只有在单例类中具有非私有构造函数的情况下,才可以扩展单例类;单例类可以具有扩展方法
        可测试性模拟静态类非常困难,特别是在包含静态对象的时候。当然如果是只有静态方法,且幂等则还是很容易测试的测试单例类很容易

        3.使用场景

        经过上面的对比,你应该看出端倪了。

        c#中单例类与静态类的区别以及使用场景

        当您只需要一个包含多个方法的工具类时,静态类是一个不错的选择,在这种情况下您不需要实例。因为您没有此类的任何实例,所以这个简单的实现提高了应用程序的性能。

        单例模式可用于设计只需要一个实例的类。典型示例包括用于日志记录,缓存,线程池等的管理器类,在这些场景,单例类是一个不错的选择。为此,您应该有一个实例,以避免对同一资源的请求冲突。

        还有在引入了DI框架后,你应该多多使用单例类,因为实现这样的需求,就是简单的定义一个普通的类,然后注册到DI中即可。

        当然还有一点就是单例类更加像面向对象编程,哈哈~~~

        来源:https://juejin.cn/post/6914855227006910478

        标签:c#,单例类,静态类
        0
        投稿

        猜你喜欢

      • C#获取本地IP的四种方式示例详解

        2023-04-16 00:52:50
      • 详解spring-boot actuator(监控)配置和使用

        2022-07-12 17:20:37
      • C#实现滑动开关效果

        2023-11-26 22:18:29
      • Android 检测键盘显示或隐藏键盘的实现代码

        2022-09-08 09:14:05
      • Android基于TextView实现的跑马灯效果实例

        2023-10-07 02:45:05
      • springboot如何通过URL方式访问外部资源

        2022-02-07 01:10:15
      • C#读取或设置ScrollLock状态的方法

        2023-03-14 21:41:24
      • Java 多线程并发AbstractQueuedSynchronizer详情

        2022-12-22 10:54:35
      • Android通过访问网页查看网页源码实例详解

        2023-10-05 03:09:11
      • Java实现图片验证码功能

        2021-12-07 12:58:55
      • Android按钮按下的时候改变颜色实现方法

        2021-09-24 20:15:39
      • Java应用层协议WebSocket实现消息推送

        2022-05-09 07:26:29
      • Webview实现android简单的浏览器实例代码

        2023-04-20 15:21:57
      • Java基础之Spring5的核心之一IOC容器

        2022-06-04 07:44:14
      • Android三种GSM手机定位技术分析

        2023-04-10 10:09:22
      • android仿音悦台页面交互效果实例代码

        2023-03-27 12:55:54
      • 利用C#实现可以继承的"枚举"

        2021-08-08 20:55:50
      • C语言形参和实参的区别详解

        2023-08-27 19:41:53
      • eclipse怎么引入spring boot项目插件的方法

        2021-07-23 20:38:54
      • java内存泄漏与内存溢出关系解析

        2023-08-07 01:58:59
      • asp之家 软件编程 m.aspxhome.com