說說設計模式~單件模式(Singleton)


返回目錄

單件模式(Singleton)要求一個類有且僅有一個實例,並且提供了一個全局的訪問點。

從概念上來研究一下它的實現,不考慮線程安全

 1 public sealed class Singlton
 2 {
 3     static Singlton instance = null;
 4     private Singlton() { }
 6  
 7     public static Singlton Instance
 8     {
 9         get
10         {
11             if (instance == null)
12             {
13                 instance = new Singlton();
14             }
15             return instance;
16         }   
17     }   
18 }

上面的實現方式,對於多線程會有問題,因為Singlton 對象可能不指一次被創建,而罪魁禍首就是if (instance == null)這句話,它並不是線程安全的。

如果希望實現線程安全的單件,我們最先想到的應該就是借助lock機制來實現,代碼可能是這樣:

 1 public sealed class Singlton
 2 {
 3     static Singlton instance = null;
 4  
 5     static readonly object o = new object();
 6  
 7     Singlton()
 8     { }
 9  
10     public static Singlton Instance
11     {
12         get
13         {
14             lock (o)
15             {
16                 if (instance == null)
17                 {
18                     instance= new Singlton();
19                 }
20             21             }
return instance;
22 } 23 } 24 }

而我們使用靜態對象在靜態結構方法里為它進行初始化,這種方式也非常在程序中看到,如:

 1 public sealed class Singlton
 2 {
 3     static readonly Singlton instance = null;
 4  
 5     static Singlton()
 6     { instance = new Singlton();}
 7  
 8     public static Singlton Instance
 9     {
10         get
11         {
12             return instance;
13         }
14     }
15 }

這種方法及其它單件模式有一個問題,就是如果希望去更新單件對象的值,是無法實現的,比如,instance對象希望從數據庫中取出一個列表,而列表的信息有可能

發生變化,怎樣保證instance里取的是最新的信息呢,這樣我們可以在單件中引入時間觸發器的概念,代碼如下:

 1     public class CategoryRepository : Car_RentalRepositoryBase, ICategoryRepository
 2     {
 3         #region 靜態樹結構,每1分鍾去獲一下數據庫
 4         static List<Category> categoryList = null;
 5         /// <summary>
 6         /// 數據實體
 7         /// </summary>
 8         public static volatile List<Category> Instance = null;
 9         static CategoryRepository categoryRepository = new CategoryRepository();
10         static System.Timers.Timer sysTimer = new System.Timers.Timer(600000);
11         static CategoryRepository()
12         {
13             Reload();//第一次加載
14             sysTimer.AutoReset = true;
15             sysTimer.Enabled = true;
16             sysTimer.Elapsed += new System.Timers.ElapsedEventHandler(sysTimer_Elapsed);
17             sysTimer.Start();
18         }
19 
20         /// <summary>
21         /// 被訂閱了Elapsed事件的方法,每隔一段時間去重新獲取數據列表
22         /// </summary>
23         /// <param name="sender"></param>
24         /// <param name="e"></param>
25         static void sysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
26         {
27             Reload();
28         }
29 
30         internal static void Reload()
31         {
32             categoryList = categoryRepository.GetModel().OrderBy(i => i.SortNumber).ToList();
33             Instance = categoryList.Where(i => i.ID != 1).ToList();
34         }
35 }

這種方式解決了實例不能獲取最新的問題。

最后,奉獻出國外牛人寫了的泛型單件類,如果實現的類直接繼承它即可。

 1  /// <summary>
 2     /// 泛型單例基類
 3     /// </summary>
 4     public abstract class Singleton<TEntity> where TEntity : class
 5     {
 6         private static readonly Lazy<TEntity> _instance
 7           = new Lazy<TEntity>(() =>
 8           {
 9               var ctors = typeof(TEntity).GetConstructors(
10                   BindingFlags.Instance
11                   | BindingFlags.NonPublic
12                   | BindingFlags.Public);
13               if (ctors.Count() != 1)
14                   throw new InvalidOperationException(String.Format("Type {0} must have exactly one constructor.", typeof(TEntity)));
15               var ctor = ctors.SingleOrDefault(c => c.GetParameters().Count() == 0 && c.IsPrivate);
16               if (ctor == null)
17                   throw new InvalidOperationException(String.Format("The constructor for {0} must be private and take no parameters.", typeof(TEntity)));
18               return (TEntity)ctor.Invoke(null);
19           });
20 
21         public static TEntity Instance
22         {
23             get { return _instance.Value; }
24         }
25     }

感謝您好閱讀,希望本文章對您有幫助。

相關鏈接:基礎才是重中之重~延遲初始化

參考 文獻:

http://technet.microsoft.com/zh-cn/magazine/dd997286%28VS.95%29.aspx

http://www.fascinatedwithsoftware.com/blog/post/2011/07/13/A-Generic-Singleton-Class.aspx

 

返回目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM