简单的研究了一下单例模式
之前我喜欢只是单纯的记记笔记,没有什么写文章的习惯,今天也是我一边研究一边学习,索性就连过程什么的都记录下吧,或许能帮到一两个朋友呢。
首先,我们来想想什么叫做单例,顾名思义,单一的一个对象,那么,单一模式有什么好处呢?比如说,你的对象只可以实例化一次等等。
先写一个简单的测试里的例子吧,比如我建一个类,叫做TestSingle
1 /// <summary> 2 /// 单例模式简单的例子(sealed,不可继承) 3 /// </summary> 4 public sealed class TestSingle 5 { 6 }
首先要让这个类不可继承,要不然就没有意义了,那么,接下来做什么呢?让一个对象只实例化一次,从而降低等等一些乱七八糟的东西。专业名词很多,百度搜搜就可以看到了。我们在实例化一个对象会做什么呢?肯定是new一个对象了,那么new对象的时候会发生什么事情呢?就是执行构造函数,那如何让我们这个类只实例化一次呢?看样子只能从构造函数入手了。
1 /// <summary> 2 /// 用来记录构造函数执行的次数 3 /// </summary> 4 private static int structureCount = 0; 5 6 /// <summary> 7 /// 私有的无参构造函数 8 /// </summary> 9 private TestSingle() 10 { 11 structureCount++; 12 Console.WriteLine("只是第{0}次执行构造函数", structureCount); 13 }
首先我定义了一个静态的变量用来存储构造函数执行的次数,并在构造函数中输出执行的次数。当我把构造函数私有化之后,如何通过别的方式来让外界访问到呢?我们来写一个public的方法,来提供外界的调用,当然,这个方法也是一个静态的方法。
1 /// <summary> 2 /// 实例化时执行的此处 3 /// </summary> 4 private static int createStructureCount = 0; 5 6 /// <summary> 7 /// TestSingle 8 /// </summary> 9 private static TestSingle testSingle = null; 10 11 12 /// <summary> 13 /// 创建一个testSingle的实例 14 /// </summary> 15 /// <returns></returns> 16 public static TestSingle CreateTestSingle() 17 { 18 createStructureCount++; 19 Console.WriteLine("我是第{0}次创建TestSingle实例化", createStructureCount); 20 testSingle = new TestSingle(); 21 return testSingle; 22 }
这样写和一个普通的new又有什么区别?我们来把方法改造一下
1 /// <summary> 2 /// 创建一个testSingle的实例 3 /// </summary> 4 /// <returns></returns> 5 public static TestSingle CreateTestSingle() 6 { 7 createStructureCount++; 8 Console.WriteLine("我是第{0}次创建TestSingle实例化", createStructureCount); 9 if (testSingle == null) 10 { 11 testSingle = new TestSingle(); 12 } 13 return testSingle; 14 }
我们去执行一下测试一下看效果如何。
我们可以看到构造函数被执行了两次,我电脑的CPU性能并不是很好,如果好一点的电脑可能会执行更多次。那么我是怎么进行测试的呢?我写了一个线程工厂,不停的去CreateTestSingle
1 static void Main(string[] args) 2 { 3 //创建一个Task工厂 4 TaskFactory taskFactory = new TaskFactory(); 5 for (int i = 0; i < 20; i++) 6 { 7 taskFactory.StartNew(() => TestSingle.CreateTestSingle()); 8 } 9 Console.ReadLine(); 10 }
也就是说,在很多个线程同时去Create的时候,不妨还是new了多个对象。所以光这样是不行的,所以我加了一个锁和双层判断
1 /// <summary> 2 /// 锁定对象 3 /// </summary> 4 private static object lock_SingleTest = new object(); 5 6 /// <summary> 7 /// 创建一个testSingle的实例 8 /// </summary> 9 /// <returns></returns> 10 public static TestSingle CreateTestSingle() 11 { 12 if (testSingle == null) 13 { 14 lock (lock_SingleTest) 15 { 16 if (testSingle == null) 17 { 18 testSingle = new TestSingle(); 19 } 20 21 } 22 } 23 createStructureCount++; 24 Console.WriteLine("我是第{0}次创建TestSingle实例化", createStructureCount); 25 return testSingle; 26 }
再次执行一次
这样的话,不管我执行多少次,构造函数都始终只会被执行一次。大家可以让线程睡眠后再打印看看结果,那样我想你就可以看的出来效果了。哦了,这样我们就把单例模式创建完了。