当前位置:首页 » 《随便一记》 » 正文

C#中的单例模式

8 人参与  2024年11月02日 15:21  分类 : 《随便一记》  评论

点击全文阅读


C#中的单例模式


文章目录

C#中的单例模式一、什么是单例模式?二、单例模式的实现方式1.通过静态字段实现2.通过属性的get实现3.通过Lazy实现单例模式4.通过DependencyInjection 总结


一、什么是单例模式?

单例模式是一种确保一个类只有一个实例的设计模式。比如在各种工具类中,每次需要访问这个类的方法时,都实例化一个实例,这是明显不合适的

二、单例模式的实现方式

1.通过静态字段实现

代码如下(示例):

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

上述是最简单而且是以线程安全的方式实现的单例模式
1.利用静态字段确保访问Instance时,不会重复实例化单例类,这是利用静态字段只会初始化一次的特性来实现的。
2.readonly字段确保了外部使用该实例时无法更改该Instance,例如Singleton.Instance=null是报错的。
3.私有构造函数确保无法在外部实例化该类,例如new Singleton()是报错的。
不过上述方法有两个弊端:

缺点1:不符合字段的命名方式,字段命名的方式一般有三种,比如instance_instance或者m_instance
这个缺点可以很好的进行规避,再加一个对应的属性,并将该字段的访问级别更改为private即可。

代码如下:

public class Singleton{//将字段访问属性更改为私有private static readonly Singleton _instance = new();//添加一个只读属性public static Singleton Instance{get => _instance;}private Singleton(){}}

缺点2:无法彻底实现懒加载

如果当上述单例类中,只存在一个Instance静态属性和_instance字段,再没有其他静态成员时,是可以实现懒加载的。

这是由于静态成员的特点所决定的,当一个类中存在多个静态成员时,第一次访问任意一个静态成员,都会导致所有的静态成员被初始化。但是当我们确保一个类中只有一个可被访问的静态成员,也可以实现懒加载

由于这种方法存在限制,所以一般不使用这种方式实现懒加载

2.通过属性的get实现

代码如下(示例):

public class Singleton{//不再直接实例化_instance    private static Singleton _instance;    public static Singleton Instance    {        get        {            if (_instance == null)            {                _instance = new Singleton();            }            return _instance;        }    }    private Singleton()    {    }}

上述方式虽然实现了懒加载,但是无法确保线程安全
实现线程安全的方式很简单,加入lock线程锁:

public class Singleton{    private static Singleton _instance;    private static readonly object _lock = new();    public static Singleton Instance    {        get        {            lock (_lock)            {                if (_instance == null)                {                    _instance = new Singleton();                }            }            return _instance;        }    }    private Singleton()    {        Console.WriteLine("构造函数初始化");    }}

这种方式完美的实现了单例以及懒加载,但是仍然有一个缺点,就是每次访问该属性时,不论_instance是否被实例化,都会访问lock块,导致不必要的资源开销,所以我们在lock之前先判断一下_instance是否被实例化,如果已被实例化,则直接返回,这就是双检查实现单例。

代码如下(示例):

public class Singleton{    private static Singleton _instance;    private static readonly object _lock = new();    public static Singleton Instance    {        get        {        //保证效率,实例化后不再进入lock块        if (_instance == null)            {            //确保线程安全               lock (_lock)            {                if (_instance == null)                {                    _instance = new Singleton();                }            }            }            //已经被实例化直接返回            return _instance;        }    }    private Singleton()    {    }}

通过双检查实现的单例模式即实现了懒加载,同时又保证了线程安全,但是还有没有更简洁的方式来实现单例呢,下面进一步探讨

3.通过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()    {    }}

可以看到通过使用Lazy,代码相比双检查,不再需要手动编写锁定代码,而且Lazy提供了工厂方法,可以在工厂方法中更灵活的初始化实例,比如()=>new Singleton{Prop1 = 1,...},并且能灵活配置是否需要线程安全。
通过以上方式我们实现了非常简洁的单例实现,同时保证了线程安全以及懒加载,那么还有没有其他方式?

4.通过DependencyInjection

代码如下:

using Microsoft.Extensions.DependencyInjection;var serviceCollection = new ServiceCollection();serviceCollection.AddSingleton<Service>();var serviceProvider = serviceCollection.BuildServiceProvider();var service = serviceProvider.GetService<Service>();service.Func();public class Service{    public void Func()    {        Console.WriteLine("Hello World");    }}

DI容器通过提供AddSingleton这种方式实现了类的生命周期管理,表示在整个生命周期中该实例都是单例,同时AddSingleton还提供了多个重载,比如提供工厂方法的重载,可以调用不同的构造方法,比如AddSingleton<Service>((provider)=>new Service(param1,...))

总结

通过上述实现单例模式的各种方法的探讨,我们还需要在实际开发过程中,根据不同的需求来进行选择不同的实现方式。比如一个比较小的项目,后续改动不大,可以通过第一种public static readonly Singleton Instance = new();来实现;比如我们开发ASP.Net,这时我们就需要用到DependencyInjection这种方式


点击全文阅读


本文链接:http://zhangshiyu.com/post/181531.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 祖母寿宴,侯府冒牌嫡女被打脸了(沈屿安秦秀婉)阅读 -
  • 《雕花锦年,昭都旧梦》(裴辞鹤昭都)完结版小说全文免费阅读_最新热门小说《雕花锦年,昭都旧梦》(裴辞鹤昭都) -
  • 郊区41号(许洛竹王云云)完整版免费阅读_最新全本小说郊区41号(许洛竹王云云) -
  • 负我情深几许(白诗茵陆司宴)完结版小说阅读_最热门小说排行榜负我情深几许白诗茵陆司宴 -
  • 九胞胎孕妇赖上我萱萱蓉蓉免费阅读全文_免费小说在线看九胞胎孕妇赖上我萱萱蓉蓉 -
  • 为保白月光,侯爷拿我抵了债(谢景安花田)小说完结版_完结版小说全文免费阅读为保白月光,侯爷拿我抵了债谢景安花田 -
  • 陆望程映川上官硕《我的阿爹是带攻略系统的替身》最新章节阅读_(我的阿爹是带攻略系统的替身)全章节免费在线阅读陆望程映川上官硕
  • 郑雅琴魏旭明免费阅读_郑雅琴魏旭明小说全文阅读笔趣阁
  • 头条热门小说《乔书意贺宴临(乔书意贺宴临)》乔书意贺宴临(全集完整小说大结局)全文阅读笔趣阁
  • 完结好看小说跨年夜,老婆初恋送儿子故意出车祸_沈月柔林瀚枫完结的小说免费阅读推荐
  • 热推《郑雅琴魏旭明》郑雅琴魏旭明~小说全文阅读~完本【已完结】笔趣阁
  • 《你的遗憾与我无关》宋怀川冯洛洛无弹窗小说免费阅读_免费小说大全《你的遗憾与我无关》宋怀川冯洛洛 -

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1