• 说说设计模式~单件模式(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

    返回目录

  • 相关阅读:
    java RSA 加签验签【转】
    json遍历 分别使用【原】
    oracle 递归和connect by【转】
    css before after基本用法【转】
    Java Web基础——Action+Service +Dao三层的功能划分
    JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分
    UUID
    在ssh框架中service-action-jsp-formbeam-dao的调用顺序
    Singleton模式(单例模式)
    真正理解、区分Action,Service和Dao功能
  • 原文地址:https://www.cnblogs.com/lori/p/2560005.html
Copyright © 2020-2023  润新知