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.使用场景
经过上面的对比,你应该看出端倪了。
当您只需要一个包含多个方法的工具类时,静态类是一个不错的选择,在这种情况下您不需要实例。因为您没有此类的任何实例,所以这个简单的实现提高了应用程序的性能。
单例模式可用于设计只需要一个实例的类。典型示例包括用于日志记录,缓存,线程池等的管理器类,在这些场景,单例类是一个不错的选择。为此,您应该有一个实例,以避免对同一资源的请求冲突。
还有在引入了DI框架后,你应该多多使用单例类,因为实现这样的需求,就是简单的定义一个普通的类,然后注册到DI中即可。
当然还有一点就是单例类更加像面向对象编程,哈哈~~~
来源:https://juejin.cn/post/6914855227006910478


猜你喜欢
- 在c和c++中,我们知道没办法起一个变量名叫int,因为这是C/C++保留的关键字,起这么一个变量名没办法区分到底是int类型还是int变量
- Random类 (java.util) Ran
- 1.spring配置文件<bean id="configproperties"  
- 先上代码新建一个Thread,代码如下:package com.thread.test;public class MyThread exte
- Mybatis映射文件mapper.xml的注释问题从昨天夜晚9点到今天中午,一直被项目bug所困惑,中间这段时间一直未解决这个问题,也咨询
- Webview打开本地图片选择器十分之麻烦,其在安卓系统3x 4x 5x上的行为都不同,处理也不同,所以之前差点崩溃。经过测试和完善,最终其
- iText下载页面: http://sourceforge.net/projects/itext/files/1.创建简单的PDF文件pac
- import java.io.ByteArrayInputStream; import java.io.FileOutputSt
- 最近有一个java实验,要求用java使用数据库,于是本人新手小白,在idea上卡了好半天希望看到这个博客的人能解决问题,跳过一些坑首先,我
- 前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题。本篇主要从实例的角度分享下CORS
- 根据中国的国情,宽带共享遭受dns污染和HTTP拦截非常严重,造成网络请求的不稳定.但是ip/tcp协议一般不受影响。因此可以把域名先解析成
- 本文实例为大家分享了java实现通讯录管理系统的具体代码,供大家参考,具体内容如下完成项目的流程:1.根据需求,确定大体方向 2.功能模块分
- JAVA 静态代理模式代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。代理模式说白了就是“真实对象”的代表,在访问对象
- 通过JDK的Proxy代理实现对业务类做简单的AOP实现接口:UserService 包含的方法为切入点,会被代理拦截类:UserServi
- 有时候我们需要多列表中的数据进行特定的排序,最近项目中用到的是按名称排序,所以简单来说一下:效果图:排序方法:Collections.sor
- 在新建Java项目时,run运行main方法时,报错 “java: 错误: 无效的源发行版:16”,
- 本文实例讲述了Java实现的简单网页截屏功能。分享给大家供大家参考,具体如下:package awtDemo;import java.awt
- 一、项目运行环境配置:Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe
- import java.util.Arrays;/** * 栈的实现<br> * @author Skip&
- 思路今天带大家实现一个上拉加载更多的ListView.GitHub传送门:PulmListView, 欢迎大家fork&&s