Tuesday, January 15, 2008

Singleton Pattern Framework Code

Keywords: C#, Design Pattern, Singleton


The following code block is the most simple, however it is thread-safe. Refer to http://msdn2.microsoft.com/en-us/library/ms954629.aspx



// .NET Singleton
sealed class Singleton
{
private Singleton() {}
public static readonly Singleton Instance = new Singleton();
}

some more complex implemention are as follows,




/// <summary>

/// Class implements singleton pattern.

/// </summary>

public class Singleton

{

// Private constructor to avoid other instantiation

// This must be present otherwise the compiler provide

// a default public constructor

private Singleton()

{

}



/// <summary>

/// Return an instance of <see cref="Singleton"/>

/// </summary>

public static Singleton Instance

{

get

{

/// An instance of Singleton wont be created until the very first

/// call to the sealed class. This a CLR optimization that ensure that

/// we have properly lazy-loading singleton.

return SingletonCreator.CreatorInstance;

}

}



/// <summary>

/// Sealed class to avoid any heritage from this helper class

/// </summary>

private sealed class SingletonCreator

{

// Retrieve a single instance of a Singleton

private static readonly Singleton _instance = new Singleton();



/// <summary>

/// Return an instance of the class <see cref="Singleton"/>

/// </summary>

public static Singleton CreatorInstance

{

get { return _instance; }

}

}

}

上面的代码没有考虑singleton对象的线程安全问题. 在用VS2005向导生成Settings类和Resource类的时候, 你会注意到Setting类需要考虑线程同步问题, 因为程序可能不仅仅会读取外部的config文件, 也有可能会修改config文件的信息. 而Resource类不需要考虑线程同步的问题, 因为一般程序不会修改Resource.res的文件.


那么怎样为singleton类增加线程同步问题呢? 查看Settings.Designer.cs文件, 会发现在创建defaultInstance时候, 用了下面的代码:


private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));


通过Reflector工具, 可以看到ApplicationSettingsBase.Synchronized()方法是个static方法, 传入的参数就是一个Settings类的实体, 这个方法仅仅是将settings对象的 IsSynchronized属性设置为True, 再看一下ApplicationSettingsBase类的Save()方法, 读取的方法和Save()方法类似. 就明白它是怎样完成线程同步的.




//ApplicationSettingsBase class

public virtual void Save()

{

if (this.IsSynchronized)

{

lock (this)

{

this.SaveCore();

return;

}

}

this.SaveCore();

}


No comments: