使用单例而不是全局静态实例

时间:2010-04-06 22:56:28

标签: c# singleton

我今天遇到了一个问题,一位朋友建议我使用全局静态实例或更优雅地使用单例模式。我花了几个小时阅读单身人士,但有些事情仍然让我感到厌烦。

背景: 我想要完成的是创建一个API的实例并在我的所有类中使用这个实例(而不是建立新的连接等)。

似乎有大约100种创建单例的方法,但在yoda的帮助下,我发现了一些线程安全的例子。 ..还给出了以下代码:

public sealed class Singleton
{
     public static Singleton Instance { get; private set; }

     private Singleton()
     {
        APIClass api = new APIClass();  //Can this be done?
     }

     static Singleton() { Instance = new Singleton(); }
}

如何/在哪里实例化这个新类以及如何从一个单独的类中调用它?

编辑: 我意识到Singleton类可以用类似

的方式调用
Singleton obj1 = Singleton.Instance();

但是我能够访问API类中的方法(即obj1.Start)吗? (不是我需要,只是问)

编辑#2:我可能在检查答案时有点过早,但我确实有一件小问题仍在引起我的问​​题。 API启动很好,遗憾的是我能够启动两个实例吗?

新代码

public sealed class SingletonAPI
{
 public static SingletonAPI Instance { get; private set; }

 private SingletonAPI() {}

 static SingletonAPI() { Instance = new SingletonAPI(); }     

 // API method:
 public void Start() { API myAPI = new API();}
 }

但如果我尝试做这样的事情......

SingletonAPI api = SingletonAPI.Instance;
api.Start();
SingletonAPI api2 = SingletonAPI.Instance;  // This was just for testing.
api2.Start();

我收到错误消息,说我无法启动多个实例。

3 个答案:

答案 0 :(得分:9)

为什么不直接向您的单身人士添加公共APIClass属性?

public sealed class Singleton
{
     public static Singleton Instance { get; private set; }

     private APIClass _APIClass; 

     private Singleton()
     {
        _APIClass = new APIClass();  
     }

     public APIClass API { get { return _APIClass; } }

     static Singleton() { Instance = new Singleton(); }     
}

然后您的呼叫网站如下:

Singleton.Instance.API.DoSomething();

或者,如果您是API类的作者,您可以将其设为单身,而不是将其包装在单个类中:

public sealed class SingletonAPI
{
     public static SingletonAPI Instance { get; private set; }

     private SingletonAPI() {}

     static SingletonAPI() { Instance = new SingletonAPI(); }     

     // API method:
     public void DoSomething() { Console.WriteLine("hi"); }
}

API调用:

SingletonAPI.Instance.DoSomething();

答案 1 :(得分:5)

这是official Microsoft approach

单例的优点在于您可以在代码中的任何位置使用和访问它,而无需创建类的实例。事实上,这是它的存在理由,一个类的单个实例,例如

Singleton.Instance.MyValue Singleton.Instance.DoSomething();

答案 2 :(得分:3)

您不会实例化该类 - 您使用的模式在第一次使用时基本上实例化。您正在使用的方法的优点是它的线程安全(只会实例化一次,无论有多少线程尝试访问它),懒惰(在您尝试访问Singleton类之前不会实例化),并且简单在实施中。

您需要做的就是:

 Singleton.Instance.MyMethodOnSingleton();

或者,或者:

 Singleton myInstance = Singleton.Instance; // Will always be the same instance...
 myInstance.DoSomething();