面对现实,超越自己
逆水行舟,不进则退
posts - 269,comments - 32,trackbacks - 0

      singleton模式是Gof提出的23中模式之一,也称为单例模式,那么简单说一下,什么叫单例模式呢?
      通常我们创建类的对象是使用new Object(),然后就调用该对象里面的方法,那么当我们多次使用new Object()的话,会对系统资源造成一种浪费,当然.net内部已经有垃圾回收机制可以处理这种浪费。当然我们并不会再程序里面多次使用new Object(),但是,作为一个类的设计者,我们需要负什么责任,除了让别的模块可以调用使用之外,我们的设计还需要一种规范,这也是OO里面的规范,singleton模式在这里派上了用场。

      singleton模式的意图:确保一个类只能拥有一个实例,并保证逻辑的正确性以及良好的效率,并提供一个该实例的全局访问点。
      singleton模式类型:单线程singleton,多线程singleton
      singleton思路:要让使用者只能使用一个实例的话,那么必须绕过常规的公有缺省构造器

      singleton代码:

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

      第4行:利用私有构造函数绕开系统自带的缺省公有构造函数,这样就使类的外部不可以直接使用new实例化对象
      第5行:提供一个静态的公有属性,供类外部调用
      第9行:在这里可能存在BUG,当有两个线程同时操作公有属性时,常规的话应该返回两个一样的实例,但是假如当第一个实例还未来得及创建时,第二个线程又访问了它,显然也会执行              new singleton()这个语句,那么这两个对象的引用就不一样了,可以使用object.ReferenceEquals测试一下对象的引用是否一样。因此,给大家提供多线程方案,请看下面代码

 1 public class singletons
 2 {
 3     private static volatile singletons instances = null;
 4     private static object lockHelper = new object(); 
 5     private singletons() { }
 6     public static singletons Instance
 7     {
 8         get
 9         {
10             if(instances==null)
11             {
12                 lock (lockHelper)
13                 {
14                     if(instances==null )
15                     {
16                         instances = new singletons();
17                     }
18                 }
19             }
20             return instances;
21         }
22     }
23 }

      显然看起来与单线程singleton差不多,多了volatile 修饰符,还有一个Object对象,接下来跟大家解释使用这些其中的缘由
      volatile 修饰符
      假如我定义两个变量和两个属性

 1  int a;
 2  volatile int b;
 3  public int GetFirst
 4  {
 5      get { return a; }
 6  }
 7  public int GetSecond
 8  {
 9      get { return b; }
10  }

      GetFirst会得到当前线程中a的值,而多个线程就会有多个a的变量拷贝,而且这些拷贝之间可以互不相同,换句话说,另一个线程可能改变了它线程内的a值,而这个值和当前线程中的a值不相同,那么就造成线程冲突了。
那么再来看看b,因为volatile 修饰的变量不允许有不同于“主”内存区域的变量拷贝,换句话说,一个变量经volatile 修饰后在所有线程中都是同步的;任何线程改变了它的值,所以其他线程立即获取到了相同的值,当然加了volatile 修饰的变量存储时会比一般变量消耗的资源要多一点。

Object对象锁
      对象锁可以保证Lock里面的代码只能同时让一个线程执行,所以确保了一个对象只存在一个实例。

      同样的需求可以有不同的方法实现,以下是另外一种实现singleton模式的代码,代码更简单,不够有缺陷,请看

1 public class singletonss
2  {
3      public static readonly singletonss Instance = new singletonss();
4      private singletonss() { }
5  }

      首先定义一个静态的只读实例,当然也需要私有构造器绕过缺省构造器,这样子也可以保证多线程里也只诞生一个对象实例,因为.Net类型初始化机制保证只有一个线程执行了静态构造器。当然这么少的代码也可以实现singleton,但是静态构造器不支持参数,也不能重构,因为在.Net机制里面只允许一个类拥有一个静态构造器而且是私有的,外部不能调用只能供系统调用,所以我们不能使用参数。

本文转自:http://www.cnblogs.com/magicchaiy/archive/2010/12/02/1894826.html
其他链接:http://www.cppblog.com/dyj057/archive/2005/09/20/346.html

posted on 2012-07-13 08:14 王海光 阅读(411) 评论(0)  编辑 收藏 引用 所属分类: Design Pattern

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理