设计模式-单例模式

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

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

    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 多线程无参数单例模式

    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特性多线程无参数单例模式

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

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

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

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

        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 有参数单例模式

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

 //单线程
    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;
            
        }
    }

多线程:

//多线程
    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特性的代码,大家直接声明字段然后赋值就可以了,这里就不示范了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maybe_ch

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值