ASP.NET2.0

网站开发

老生常谈:单件模式

    单件模式有以下的特点

    1 :单件类只可有一个实例。

    2 :单件类必须自己创建自己这惟一的实例。

    3 :单件类必须给所有其他对象提供这一实例。

 

     一般创建单件我们常用的有两种方式:


     1:静态变量法,也叫惰性实例化
     2:双重锁定


     静态变量法非常好理解,.net的运行机制决定了静态变量可以形成单件,静态变量是一个存储在内存中的变量.它的机制可以保证同一时间只会存在一个变量.为此我们非常容易的可以写出这样的程序:
   

    1:   

Code

 

    这种对于单线程运行的程序来说是绝对没有问题的,例如运行一个asp.net程序,一般网站都基本用不到多线程,所有上面的例子就足够满足.但是如果是多线程呢?如果同时有两个线开始判断instance==null,如果此时都为真,则创建了两上实例,这样就违背了单件的原则.为此可进行下修改:

 

    2:   

Code

 

    这种方法在程序初始化时对类实例进行了初始化,利用静态变量以及私有构造方法完成了单件的生成.之所以称这种方式是惰性实例化,是因为,无论你是否调用这个实例,它都会被创建.


    双重锁定:


    我们可以对方法1进行下改造,它的缺点就是非线程安全,既然有缺点当然就要改正了.

    3:    

Code

 

     这个方法是线程式安全的单件模式,但是它每次生成单件的时候都要给对象加锁,这样也是一种性能消耗.上面说了有缺点就要改,这个方法当然也不例外:

   

     4:     

Code

 

    

      这个方法在生成的实例的时候,先判断是否为空,如果不为空则不对对象进行加锁操作直接返回对象实例.同时这种双重锁定对比静态方法来看,有一个优势就是它的实例化延迟到类中,只有调用此类的实例时它才会生成实例.

 

      上面都是常规的单件模式,其实并不是所有的情况都如上面一样.在抽象工厂的应用中经常结合单件模式来应用,使得工厂实例是唯一的.在上一篇 用抽象工厂模式武装新闻组件  中,我用上了抽象工厂,当时在抽象工厂类实例的生成上并没有结合单件模式,所在在这想改造一下.我的程序思路是这样的,有一个抽象工厂基类AbstractFactoryClass,它包含一个public static AbstractFactoryClass GetInstance()方法,作用是生成它的派生类的实例,而这个生成过程是通过反射来完成的.这两个派生类分别是:AbstractFactory_China,AbstractFactory_US.这种情况下要想直接返回AbstractFactoryClass的实例是不可能的,因为它是抽象类,不能直接new AbstractFactoryClass().

     

       先看下这三个类的类图:

      

 

      代码如下:

    

 

Code

 

 

     上面的代码因为基类是抽象类所有没有上面常规程序中的私有构造函数,这种生成抽象工厂类派生类实例的案例并不适用于静态方法构造单件的情况,因为你不能直接通过new的方式来初始化类实例.


     我老生常谈的理由有二:
     1:所谓能看懂并不一定理解,理解并不一定能做,能做并一定应用的好.虽然已经有很多园友写过相关的文章,但是我自己并没有写过,自己把自己的理解通过代码的形式表现出来也是一种自我提高.
     2:设计模式是编程人员能力的一方面,经典的东西并不会因为时间的流逝而失宠.

 

   注:

      1:本文相关内容有部分摘自网络.

      2:引用:http://terrylee.cnblogs.com/archive/2005/12/09/293509.html

 

Tag标签: C#,.NET

posted on 2008-07-30 13:22 姜敏 阅读(1484) 评论(34)  编辑 收藏 所属分类: 设计模式

Feedback

#1楼  2008-07-30 13:26 包建强      

话说,这篇文章写得   回复  引用  查看    

#2楼 [楼主] 2008-07-30 13:29 姜敏      

@包建强
包兄有什么意见不妨真说啊,为何说一半呢?   回复  引用  查看    

#3楼 [楼主] 2008-07-30 13:29 姜敏      

本人在设计模式上经验并不丰富,纯属爱好及兴趣,有不足的地方希望大家指点.   回复  引用  查看    

#4楼  2008-07-30 13:43 懒的起名 [未注册用户]

我最讨厌设计模式了,听起来有道理 ,其实是百无一用的东西。
现在人们最需要的一些基础知识,新知识,经验技巧(不是模式技巧)

我并不是讨厌 设计模式, 而是现在 模式的人 太多太多了, 雨后春笋,百花挣放, 我去新华书店 设计模式的书 一排,大有超过语法,新技术的书。
就算是 当当网 设计模式都能搜出 分页来。

我们公司,现在人人都看设计模式,因为设计模式属于 “高档概念”
人人都再讲,(我们公司1人1天的演讲)

上次我就碰到了一个问题, 来了一个人还根我谈设计模式,我就根他说
滚一边去,连 正则 JQ .Net控件 都玩不熟悉 还根我这来谈。

现在就是有些人 说起模式 一套一套的, 做起程序来 百无一用型。

我的桌上还有设计模式2本呢, 但是我更喜欢 一些快速开发高效的适应性的书籍。   回复  引用    

#5楼  2008-07-30 13:48 TerryLee      

内容没仔细看,不过标题是“单件”,文章内容却是“单例”,这……

最好能够统一一个用语:)   回复  引用  查看    

#6楼 [楼主] 2008-07-30 13:51 姜敏      

@懒的起名
本人可能就是那种"连 正则 JQ .Net控件 都玩不熟悉 还根我这来谈"的人.哈哈,没办法,跟着朝流走啊。   回复  引用  查看    

#7楼 [楼主] 2008-07-30 13:51 姜敏      

@TerryLee
啊,好的,我去改下。   回复  引用  查看    

#8楼  2008-07-30 13:56 Tony Zhou      

string factoryName = ConfigurationSettings.AppSettings["factoryName"].ToString();

这个放到 if (instance == null) 里面   回复  引用  查看    

#9楼 [楼主] 2008-07-30 13:58 姜敏      

@Tony Zhou
谢谢指点,马上更改。   回复  引用  查看    

#10楼  2008-07-30 13:59 横刀天笑      

问一下,JQ.NET控件是什么控件?-_-   回复  引用  查看    

#11楼  2008-07-30 14:02 Oriesmap [未注册用户]

class Singleton
{
private static Singleton _instance = new Singleton();
private Singleton(){}

public static Singleton Instance {
get { return _instance;}
}
}
怎么样?   回复  引用    

#12楼 [楼主] 2008-07-30 14:02 姜敏      

@横刀天笑
我想那位仁兄可能说的是
jquery,和.net控件吧,猜的.   回复  引用  查看    

#13楼  2008-07-30 14:03 xuyan      

看看   回复  引用  查看    

#14楼  2008-07-30 14:03 横刀天笑      

@姜敏
哦,这个啊,我也不懂jquery,不过俺做WinForm的 :)
  回复  引用  查看    

#15楼 [楼主] 2008-07-30 14:04 姜敏      

@Oriesmap
private static Singleton _instance = new Singleton();
_instance最好是readonly类型的。   回复  引用  查看    

#16楼 [楼主] 2008-07-30 14:06 姜敏      

@横刀天笑
哈哈,难怪了,我是从事web这块的,所有能够猜一下,你的文章写的不错。以后多多指教。   回复  引用  查看    

#17楼  2008-07-30 14:07 预备役中尉      

看不懂,也懒得看,还是C看起来舒服.或许人老了吧.   回复  引用  查看    

#18楼  2008-07-30 14:08 Oriesmap [未注册用户]

对于最后一个例子,如果单件需要从配置中获取数据后生成,我的通常做法是做成单件的工厂之类的东西,然后把这个目标对象内部注册到工厂,调用采用类似

Singleton instance = (Singleton)factory.Instance.GetService(typeof(Singleton));
用法.
不知道楼主认为这种方法怎样?

说实话,最近看了太多的单件模式之类的东西,确实有些审美疲劳了.   回复  引用    

#19楼 [楼主] 2008-07-30 14:11 姜敏      

@Oriesmap
对于每种需要,不同的程序员有不同的做法,这是非常正常的,没有最好的解决方案,只有最适合自己的。   回复  引用  查看    

#20楼  2008-07-30 14:25 PureEviL      

由于众所周知的原因
双nullcheck不是线程安全的   回复  引用  查看    

#21楼 [楼主] 2008-07-30 14:27 姜敏      

@PureEviL
-----------
由于众所周知的原因
双nullcheck不是线程安全的
------------
有何根据呢?   回复  引用  查看    

#22楼  2008-07-30 15:24 g [未注册用户]

哈哈后哈
  回复