之前我喜歡只是單純的記記筆記,沒有什麼寫文章的習慣,今天也是我一邊研究一邊學習,索性就連過程什麼的都記錄下吧,或許能幫到一兩個朋友呢。 首先,我們來想想什麼叫做單例,顧名思義,單一的一個對象,那麼,單一模式有什麼好處呢?比如說,你的對象只可以實例化一次等等。 先寫一個簡單的測試里的例子吧,比如我建一 ...
之前我喜歡只是單純的記記筆記,沒有什麼寫文章的習慣,今天也是我一邊研究一邊學習,索性就連過程什麼的都記錄下吧,或許能幫到一兩個朋友呢。
首先,我們來想想什麼叫做單例,顧名思義,單一的一個對象,那麼,單一模式有什麼好處呢?比如說,你的對象只可以實例化一次等等。
先寫一個簡單的測試里的例子吧,比如我建一個類,叫做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 }
再次執行一次
這樣的話,不管我執行多少次,構造函數都始終只會被執行一次。大家可以讓線程睡眠後再列印看看結果,那樣我想你就可以看的出來效果了。哦了,這樣我們就把單例模式創建完了。