C#中利用泛型实现实例单件化

来源:互联网 发布:用java求水仙花数 编辑:程序博客网 时间:2024/04/28 08:48
C#中利用泛型实现实例单件化
[ 2007-8-17 13:15:00 | By: 陈晴阳 ]
 
2
推荐
http://blog.csai.cn/user1/16236/archives/2007/17475.html    


C#中利用泛型实现实例单件化
在多线程应用程序中,实现对象的单件(GoF Singleton模式)化是一项常用的设计方法。比如,对于需要维护同一资源的多线程服务器应用程序,对于表述该资源的对象实现单件模式,是一种常用的设计方法。在C#中,我们通常的做法是:
 
public class MyClass    
{
    private static volatile MyClass instance__;
    private static object syncRoot__ = new object();
 
    private SingletonGeneric()
    {
    }
    public static MyClass Instance
    {
        get
        {
            if (instance__ == null)
            {
                lock (syncRoot__)
                {
                    if (instance__ == null)
                    {
                        instance__ = new MyClass();
                    }
                }
            }
            return instance__;
        }
    }
}
 
    这种做法是C#中标准的实现单件模式的方法。设想,假如我们有多个类需要套用单件模式,那么,我们是否需要重复地编写上面的代码?
 
    其实我们可以利用C# 2.0中的泛型类型来定义单件,并通过套用的方式来使得“实例单件化”:
 
public class SingletonGeneric<T> where T : new()
{
    private static T instance__ = default(T);
    private static object syncRoot__ = new object();
 
    private SingletonGeneric()
    {
    }
    public static T Instance
    {
        get
        {
            if (instance__ == null)
            {
                lock (syncRoot__)
                {
                    if (instance__ == null)
                    {
                        instance__ = new T();
                    }
                }
            }
            return instance__;
        }
    }
}
 
那么我们在使用的时候,只需要“SingletonGeneric<MyClass>”就可以了。这样做的好处有三:
 
1、在定义单件类时,我们可以按照普通定义类的方式,而不需要考虑单件模式的具体实现,在真正需要用的地方直接套用SingletonGeneric<MyClass>即可;
 
2、当单件模式实现发生改变时,我们只需要修改SingletonGeneric<T>类,而不需要修改所有的单件类;
 
3、这种方法还可以使得系统中本不是单件类的类型单件化,比如,我的服务器应用程序采用一个Hashtable的对象来保存数据字典,那么,我只需要使用SingletonGeneric<Hashtable>的方法,就可以确保整个系统中只存在一个Hashtable对象副本。但是这样做的弊端也是显而易见:倘若应用程序需要维护两个Hashtable的单件实例,那么就会出现问题。解决方法是:定义两个继承于Hashtable的类,然后再用此方法。
 
    这种方法也是《面向模式的软件体系结构(卷2:用于并发与网络化对象的模式)》一书中提到的一种模式惯用法。在C#中采用这种办法,有一个潜在的危险就是,我们无法在泛型T上使用volatile关键字。该关键字确保指定的类型对象在编译器处理时不被优化,以保证该对象所存储的值无论在任何时候都是最新的。我目前还没有办法证明,在C#中使用单件时,如果不采用volatile关键字是否真的会出现问题,如果有问题,又是否有其它替代方法解决。
 
原创粉丝点击