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