說說設計模式~單(dan)件模式(Singleton)
單(dan)件模式(Singleton)要求一(yi)個(ge)類(lei)有(you)且(qie)僅(jin)有(you)一(yi)個(ge)實例,并且(qie)提(ti)供了一(yi)個(ge)全局的(de)訪問點。
從(cong)概(gai)念上來研(yan)究一下它的實現,不考慮(lv)線程安(an)全
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)這句話,它并(bing)不是線程(cheng)安全的(de)。
如(ru)果希望實(shi)現線程安全的(de)單件,我們最(zui)先想到的(de)應該就(jiu)是(shi)借助lock機制來實(shi)現,代碼可能是(shi)這樣:
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 }
而(er)我們(men)使用靜態(tai)對象在(zai)靜態(tai)結構方法里(li)為它(ta)進行(xing)初始化,這種方式也非常(chang)在(zai)程序中看到,如:
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 }
這(zhe)種方法及其它單(dan)件模式(shi)有一個問題(ti),就是如果希(xi)望去更新單(dan)件對象(xiang)的值,是無法實現的,比如,instance對象(xiang)希(xi)望從(cong)數(shu)據庫(ku)中取出一個列(lie)表,而列(lie)表的信息有可能
發生(sheng)變化(hua),怎樣保證(zheng)instance里取的是(shi)最新的信息呢,這樣我(wo)們可以在(zai)單件中引入時(shi)間觸發器的概念(nian),代碼如(ru)下:
1 public class CategoryRepository : Car_RentalRepositoryBase, ICategoryRepository 2 { 3 #region 靜態樹結構,每1分鐘去獲一下數據庫 4 static List<Category> categoryList = null; 5 /// <summary> 6 /// 數(shu)據實體 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 /// 被訂(ding)閱了Elapsed事(shi)件的方法,每(mei)隔一段時(shi)間去重新獲取數(shu)據列(lie)表 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 }
這種方(fang)式(shi)解(jie)決了(le)實例不能獲(huo)取最新(xin)的問題。
最后,奉獻出國(guo)外牛(niu)人寫了的泛型單件類,如果實(shi)現的類直接繼承(cheng)它(ta)即可。
1 /// <summary> 2 /// 泛(fan)型單例基類 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 }
感謝(xie)您好閱讀,希望本文章對(dui)您有幫助(zhu)。
相關鏈接:基礎才是重中之重~延遲初始化
參考 文獻:
//technet.microsoft.com/zh-cn/magazine/dd997286%28VS.95%29.aspx
//www.fascinatedwithsoftware.com/blog/post/2011/07/13/A-Generic-Singleton-Class.aspx