【发布时间】:2010-04-06 22:56:27
【问题描述】:
我今天遇到了一个问题,一位朋友建议我使用全局静态实例或更优雅的单例模式。我花了几个小时阅读有关单身人士的文章,但仍有几件事让我无法理解。
背景: 我试图完成的是创建一个 API 实例并在我的所有类中使用这个实例(而不是建立新的连接等)。
似乎有大约 100 种创建单例的方法,但在 yoda 的帮助下,我找到了一些线程安全的示例。 ..so给出以下代码:
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 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();
我收到一条错误消息,提示我无法启动多个实例。
【问题讨论】:
-
您还应该添加一个私有构造函数,以防止另一个类实例化您的 Singleton 的副本。
-
您将无法调用 api 类上的方法,因为它没有被公开。
-
确实,您可以在私有 Singleton 构造函数中实例化一个 APIClass 对象。由于私有构造函数只会被调用一次,因此从静态构造函数来看,AFAIK 看起来都不错。不过,您将 APIClass 声明为局部变量,因此范围仅在私有构造函数内。如果您想在此之外使用它,至少必须将其重新声明为私有成员。
-
附带说明,如果您已经有一个封装完整 API 的 API 类,您始终可以将 APIClass 实例化为类的静态成员,而不是将其包装在自己的 Singleton 中。
-
Farstucker,关于您的编辑#2,首先我认为您理解这一点,但在您的示例中 api 和 api2 指的是完全相同的对象 - 这是工作中的单例。其次,不要在公共方法中实例化您的 API。在单例的私有构造函数中实例化它。这样它只会被实例化一次。 (这正是我在回答中显示的内容。我不确定,也许您在编写编辑#2 后看到了我的回答)