2012年6月24日星期日

说说设计模式~单件模式

说说设计模式~单件模式

单件模式(Singleton)要求一个类有且仅有一个实例,并且提供了一个全局的访问点。

从概念上来研究一下它的实现,不考虑纯种安全

 1 public sealed class Singlton 2 { 3     static Singlton instance = null; 4     private Singlton() { } 6   7     public static Singlton Instance 8     { 9         get10         {11             if (instance == null)12             {13                 return 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 Instance11     {12         get13         {14             lock (o)15             {16                 if (instance == null)17                 {18                     return new Singlton();19                 }20                 return instance;21             }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         get11         {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.Instance11                   | BindingFlags.NonPublic12                   | 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 Instance22         {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


TAG: