说说设计模式~单件模式(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     }
时间: 2024-10-10 20:59:38

说说设计模式~单件模式(Singleton)的相关文章

设计模式 - 单件模式(singleton pattern) 详解

单件模式(singleton pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/28595349 单件模式(singleton pattern) : 确保一个类只有一个实例, 并提供一个全局访问点. 单价模式包括3个部分: 私有构造器, 静态变量, 静态方法. 具体方法: 1. 标准的单例模式: /** * @time 2014.6.5 */ package singleton; /** * @author

Design Patterns 乌蒙山连着山外山---单件模式singleton pattern

1 //包含单件实例的类Singleton 2 public class Singleton 3 { 4 //声明用于存储单件实例的变量instance 5 private static Singleton instance; 6 //定义用于标识同步线程的对象locker 7 private static Object locker = new Object(); 8 //私有的构造函数Singleton 9 private Singleton() { } 10 //公共访问的返回单件实例的函

设计模式(二)单件模式Singleton(创建型)

SINGLETON(单件)—对象创建型模式 几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销.再如大家最经常用的IM,如QQ,在同一台电脑,一个帐号只能有唯一的登录. 1. 问题 怎样确保一个特殊类的实例是独一无二的(它是这个类的唯一实例),并且这个实例易于被访问呢? 2. 解决方案 1)全局变量:一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象.因为你的

Java设计模式——单件模式

概述: 有一些对象其实我们只需要一个,比方说:线程池(threadpool).缓存(cache).对话框.处理偏好设置和注册表(registry)的对象.日志对象,充当打印机.显卡等设备的驱动程序的对象.事实上,这类对象只能有一个实例,如果制造出多个对象,就会导致许多的问题产生,例如:程序的行为异常.资源使用过量,或者是不一致的结果.--<Head First设计模式> 使用环境: 当我们的对象在逻辑上只能有一个的时候,比如说打印机.想像一下,如果我们有两个指向同一台打印机的对象,这时我们应该

单件模式(Singleton创建型)c#简单例子

单件(Singleton创建型模式)c#简单例子 需要生成一个实例时,可采用单件模式 例子中只可生成一个玩家,并对玩家进行测试.单线程例子如下: namespace singletonpattern { public partial class SingletonForm : Form { public SingletonForm() { InitializeComponent(); } private void btnDisplay_Click(object sender, EventArgs

[设计模式]单件模式

单件模式确保一个类只有一个实例并提供一个全局访问点.实现起来也很简单,如果一个类只想有一个实例的话,那么这个类将构造函数私有化,并利用一个静态变量记录这个类的唯一实例,还要提供一个静态方法返回这个类的实例. 但是单件模式在多线程情况下可能会有些问题,解决方法一是使用同步方法返回实例,二是使用急切实例化,三是使用双重检查加锁,就是先检查实例,如果不存在就进入同步块. 类图: 参考:<Head First设计模式>

[MyBean-说明书]关于插件的单件模式(singleton),插件的共享模式

[说明] 单件模式是一种用于确保整个应用程序中只有一个类实例. 想想我们的系统中有哪些方面可以应用到单件模式,比如大家常说的连接(ADOConnection)共享,其实就是指的单件模式. [MyBean中的单件模式] MyBean中插件一旦成为单件模式,框架就会帮你接管对象的生命周期.你每次调用getBean都只会产生一份实例,也就是说对象只会创建一次,不管是窗体插件还是无UI的逻辑插件. MyBean中可以通过两种方式使插件成为单件模式. 1.最简单的一种是注册的时候,参数选定为单件模式,也是

1.单件模式(Singleton Pattern)

意图:为了保证一个类仅有一个实例,并提供一个访问它的全局访问点. 1.简单实现(多线程有可能产生多个实例) public class CommonSigleton { /// <summary> /// 私有的对象 /// </summary> private static CommonSigleton instance; /// <summary> /// 构造方法为Private /// </summary> private CommonSigleton

设计模式之单件模式

一.概述 /*    一般情况下,我们建立的一些类是属于工具性质的,基本不用存储太多的跟自身有关的数据,在这种情况下,每次都去new一个对象,即增加了开销,也使得代码更加臃肿.    其实,我们只需要一个实例对象就可以.如果采用全局或者静态变量的方式,会影响封装性,难以保证别的代码不会对全局变量造成影响.    考虑到这些需要,我们将默认的构造函数声明为私有的,这样就不会被外部所new了,甚至可以将析构函数也声明为私有的,这样就只有自己能够删除自己了.    在Java和C#这样纯的面向对象的语