2

这个网站上有很多关于为什么应该避免单例的讨论,但是在任何情况下单例是有意义的并且是最好的选择吗?

我认为单例是最佳选择的一个例子是在实现身份映射时,您需要跟踪已经从映射层中的数据库加载的所有模型。在这种情况下,重要的是映射实际上是全局的,以便所有客户端代码使用映射的相同实例并且它们都访问相同的加载模型列表。最简单的解决方案似乎是将类实现为单例(或静态方法)。这是最好的方法还是有其他方法?

是否还有其他情况可以使用单例,或者它们总是不好?

4

8 回答 8

1

看到这个线程

于 2009-01-16T09:02:23.420 回答
1

单例确实有它们的用途。我将它们的用处总结为:

“Singleton 应该用于表示对象,根据基本设计或要求,最多可以有一个实例;并且存在与该对象相关联的数据或资源,这会产生可衡量的成本。” 这就是我的意思。

1)你不应该在有很多东西的情况下使用单例,但我们只是碰巧对一个感兴趣。如果可以想象系统中有两个,则显式实例化一个。

2) Singleton 的许多用途可以被具有所有静态方法和数据的类替换。如果您可以在不影响性能的情况下执行此操作,请执行此操作。

3) 如果设置对象的成本很高,则应该考虑使用 Singleton:例如,如果它是需要初始化的物理资源,或者它依赖于需要初始化的某些查找表。如果是这种情况,使用 Singleton 您可以将初始化成本推迟到第一次使用该对象,而静态类通常会在应用程序启动时进行初始化。如果从未使用过该对象,则您永远不会支付初始化成本。

于 2009-01-21T22:15:14.073 回答
1

当您只需要一个实例并希望通过设计强制执行时,应该使用单例。不应使用它,因为它会导致全局副作用。

就您而言,我认为这是有道理的,因为您只想限制该类的一个实例。

于 2009-02-19T22:49:45.777 回答
0

在不允许静态接口成员的语言中使用单例(和类似的) - 例如在 .NET 中。通过提供单例,您就有了一个可以将接口作为实例提供的实例。因此,在 .NET 中,示例可能是:

  • Comparer<T>.Default- 提供IComparer<T>排序的实现T
  • EqualityComparer<T>.Default- 提供IEqualityComparer<T>哈希/相等测试的实现T

这是达到目的的手段;这不是我们想要做的,只是一个合理的“如何”。

就“身份映射”示例而言,我个人宁愿将其保留在一个实例上,并使该实例可用于我的所有代码。除此之外,如果您可以丢弃测试之间的映射,或者具有灵活性(稍后)同时拥有多个身份映射,它有助于可测试性。

于 2009-01-16T08:54:03.250 回答
0

考虑一下您希望将应用程序中的不同事件记录到单个文件的情况。在这种情况下,单例类 Log 将很有用。由于应用程序的不同部分将访问 Log 类的同一个实例。

于 2009-01-16T08:55:48.817 回答
0

单例确实有其用途。他们也有自己的弊端,有很多理由不喜欢他们,或者为什么他们让测试变得困难。

这是对 Singleton 模式的一个小小的辩护。

有时,程序需要代表真正独特的事物或与之交互。一个例子是物理资源。例如,您不能拥有多个“标准输出”。以及 OS 进程的表示(例如 J2ME 的 Midlet)。

单例就像使用类/接口来提供封装和这样的好处,否则将是一个裸露的全局变量是值得的。

于 2009-01-16T09:18:17.057 回答
0

当您使用 Web 编程时,单例是有意义的:您通常只需要每个请求的页面输出类的一个实例,以及它的一个用户对象。但是,数据库是不同的——实现权限分离是想要多个 db 对象的一个​​很好的理由。

于 2009-01-16T09:45:19.293 回答
0

我个人的指导方针是,如果您之后可以实例化一个类的一个对象,则永远不要将一个类硬编码为单例。这使得单例在应用程序代码中非常罕见并且通常是不必要的。在使用像 Spring 这样的 DI 框架时尤其如此。

单例在框架中确实可以用作“入口点”,但规则是将它们用作“根单例”(在依赖层次结构的开头),并让其余代码尽可能少地依赖该单例可能的。

于 2009-01-16T10:13:11.890 回答