具有可触发初始化的C#单例模式
我需要一个单身人士:
我使用.NET 3.5。
我已经用Jon Skeet的实现(第5版)开始使用静态子类:
public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton()
{
Values = new[]{"quick", "brown", "fox"};
}
public static Singleton Instance { get { return Nested.instance; } }
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
除了“从外部触发初始化”之外,这几乎包括所有的方框。 由于实际初始化发生在ctor内部,所以不能发生一次以上。
这如何实现?
单身人士将会像这样使用:
public static void Main(){
//do stuff, singleton should not yet be initialized.
//the time comes to initialize the singleton, e.g. a database connection is available
//this may be called 0 or more times, possibly on different threads
Singleton.Initialize();
Singleton.Initialize();
Singleton.Initialize();
//actual call to get retrieved values, should work
var retrieveVals = Singleton.Instance.Values;
}
似乎你可以这样做:
public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton(bool loadDefaults)
{
if (loadDefaults)
Values = new[]{"quick", "brown", "fox"};
else
Values = new[]{"another", "set", "of", "values"};
}
public static Singleton Instance { get { return Nested.instance; } }
public static void Initialize() {
Nested.Initialize();
}
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton(true);
private static object instanceLock = new object();
private static bool isInitialized = false;
public static void Initialize() {
lock(instanceLock) {
if (!isInitialized) {
isInitialized = true;
instance = new Singleton(false);
}
}
}
}
}
或者创建一个将要更新的实例:
public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton()
{
Values = new[]{"quick", "brown", "fox"};
}
public static Singleton Instance { get { return Nested.instance; } }
private static object instanceLock = new object();
private static bool isInitialized = false;
public static void Initialize() {
lock(instanceLock) {
if (!isInitialized) {
isInitialized = true;
Instance.Values = new[]{"another", "set", "of", "values"};
}
}
}
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
而第三个变体基于你不可变的注释和删除嵌套类的评论:
public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton()
{
Values = new[]{"quick", "brown", "fox"};
}
private static Singleton instance;
private static object instanceLock = new object();
public static Singleton Instance {
get {
Initialize();
return instance;
}
}
public static void Initialize() {
if (instance == null) {
lock(instanceLock) {
if (instance == null)
instance = new Singleton();
}
}
}
}
如果你需要初始化以后发生,你可以设置一个可以从外部触发的Initialize方法,但是如果每次触发时这些值不同,那么它不能是静态的,这违反了Singleton模式。
根据你的没有变量的例子,我假设你只是在初始化发生时推迟(例程而不是构造函数),但是你的问题表明你需要不同的值,但是如果多个初始化紧密结合在一起,它只会初始化一次,所以我对此有点困惑。
我不确定你是否只需要一个Singleton,但是如果没有关于Initialize()是否每次运行相同的代码或具有某种类型的变量性质的信息,都不能完全回答。
您可以使用双重检查锁定模式。 只需在你的Singleton类中添加以下代码:
public sealed class Singleton
{
..........................
private static object locker = new object();
private static bool initialized = false;
public static void Initialize() {
if (!initialized){
lock(locker) {
if (!initialized){
//write initialization logic here
initialized = true;
}
}
}
}
.......................
}
链接地址: http://www.djcxy.com/p/8735.html