前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式-单例模式

设计模式-单例模式

作者头像
MaybeHC
发布2024-04-23 19:27:44
1180
发布2024-04-23 19:27:44
举报
文章被收录于专栏:技术之路

学习了单例模式,自己记一下笔记,本文从一个单例模式开始进行一步一步的演进,使用c#语言,在实现上会结合C#的特性。演进过程为 单线程无参数单例模式->多线程无参数单例模式->.net特性多线程无参数单例模式->单线程有参数单例模式->多线程有参数单例模式->.net特性多线程有参数单例模式

No.1 单线程无参数单例模式

代码语言:javascript
复制
    public class Singleton
    {
        private static Singleton instance;
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }

我们以一个最简单的单例模式起手,单例模式顾名思义就是要让该类只有一个初始化的对象,首先我们需要做的是将对象的构造方法进行私有化,这样改对象就不能在外部进行实例化new,从下图可以看到当我们进行private私有化之后,在外部已经不能访问了。

在这里插入图片描述
在这里插入图片描述

下面我们在该函数内部进行实例化,进行判空如果对象没有被实例化就进行示例化,该单例模式只试用与单线程使用。为什么只能在单线程中使用?我们可以看到在每次调用Instance的时候都会进行执行if (instance == null)进行判空,但是当在多线程的时候,有可能两个线程同时满足该条件,例如:在第一个线程判断为空后,还没有进行实例化,这时候第二个线程进行了判空,将进入该语句,这样的情况就会进行两次实例化。下面我们修改这个方法让多线程可以安全使用

No.2 多线程无参数单例模式

代码语言:javascript
复制
    public class Singleton
    {
        private static volatile Singleton instance;
        private static object lockHelper = new object();
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (lockHelper)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
        }
    }

这是一个可以多线程使用的单例模式,进行了加锁,并进行了两次判断。private static object lockHelper = new object(); 这里可以任意写一个对象,只是用于加锁使用。

No.3 .net特性多线程无参数单例模式

代码语言:javascript
复制
    class Singleton
    {
        public static readonly Singleton Instance = new Singleton();
        private Singleton() { }
    }

这段代码可以说是非常精简,可以扩展下看着更清晰

代码语言:javascript
复制
 class Singleton
    {
        public static readonly Singleton Instance;
        static Singleton()
        {
            Instance = new Singleton();
        }
        private Singleton() { }
    }

在第一种方式中我们使用了内联初始化,在.net中会将初始化内容放入构造器中初始化,因为是静态变量所以为静态初始化器所以如下面的代码。 静态初始化器执行时期:在静态字段初始化之前进行初始化,如Singleton类就是当调用Instance时会进行初始化 我们用下面的代码测试一下执行时机:

代码语言:javascript
复制
        static void Main(string[] args)
        {
            Console.WriteLine("---------");
            Singleton t1 = null;
            Console.WriteLine("---------");
            Singleton t2 = Singleton.Instance;
            Console.WriteLine("---------");
            Singleton t3 = Singleton.Instance;
            Console.ReadKey();
        }
        class Singleton
        {
        	public static readonly Singleton Instance;
        	static Singleton()
        	{
            	Console.WriteLine("静态构造器初始化");
            	Instance = new Singleton();
        	}
        	private Singleton() { }
    }

执行结果:

在这里插入图片描述
在这里插入图片描述

我们可以看到在第一次调用Instance时才会发生初始化,这样就是一个基于.net特性的单例模式。

No.4 有参数单例模式

有参数的单例模式我这里就不再详细讲解,给大家贴上代码供参考 单线程:

代码语言:javascript
复制
 //单线程
    public class Singleton
    {
        int x;
        int y;
        private static Singleton instance;
        private Singleton(int x,int y)
        {
            this.x = x;
            this.y = y;
        }
        public static Singleton GetInstance(int x, int y)
        {

            if (instance == null)
            { 
                instance = new Singleton(x, y);
            }
            else
            {
                instance.x = x;
                instance.y = y;
            }
                return instance;
            
        }
    }

多线程:

代码语言:javascript
复制
//多线程
    public class Singleton
    {
        int x;
        int y;
        private static volatile Singleton instance;
        private static object lockHelper = new object();
        private Singleton(int x,int y) {
            this.x = x;
            this.y = y;
        }
        public static Singleton GetInstance(int x,int y)
        {

            if (instance == null)
            { 
                lock (lockHelper)
                { 
                    if (instance == null)
                    {
                        instance = new Singleton(x,y);
                    }
                    else
                    {
                        instance.x = x;
                        instance.y = y;
                    }
                }
            }
            return instance;
            
        }
    }

.ne特性的代码,大家直接声明字段然后赋值就可以了,这里就不示范了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-10-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • No.1 单线程无参数单例模式
  • No.2 多线程无参数单例模式
  • No.3 .net特性多线程无参数单例模式
  • No.4 有参数单例模式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档