替代单身人士的独特资源

时间:2012-04-15 22:49:14

标签: design-patterns singleton global-variables

我一遍又一遍地阅读,应该避免出于各种原因使用单身人士。我想知道如何正确处理类表示唯一系统资源的情况。例如,使用SDL的AudioOutput类。由于SDL_OpenAudio一次只能打开一次,所以有一个这种类型的对象是没有意义的,而且在我看来,防止意外制造多于一个对象实际上是好的。

只是想知道有经验的程序员对此有什么想法,我还缺少另一种选择吗?

3 个答案:

答案 0 :(得分:9)

Singleton的一个问题是,它的使用大多数情况下会破坏控制反转原理(或依据SOLID的依赖性反转)。

Singleton不仅会阻止创建多个对象,还会公开此对象,以便从代码中的任何位置进行访问。这很糟糕,因为如果您决定更改对象的创建/访问方式,则必须更改代码中的所有位置,例如,他们应该通过静态SingletonClass.GetInstance()访问它。

此外,当您实施单元测试时,通常需要使用模拟而不是真实对象。在您的情况下,如果您想要对某些模块进行单元测试,并且该模块通过SingletonClass.GetInstance()访问实际音频输出,则用实际音频输出替换存根将变得非常困难。

另一方面,如果您的模块通过dependency injection获取音频输出对象(例如,作为传递给构造函数的参数),那么在测试时,您可以注入一个存根而不是真正的音频输出对象它实现了相同的接口。

当然,在注入此类对象的级别上,您可以使用单例来确保一次只有一个实例。重点是底层代码不应该关心可以有多少对象或者如何获取它们 - 它只适用于注入的内容。

所以作为一个底线,你可以使用Singleton,如果你真的认为它是需要的,但不允许它作为全局状态被访问。

答案 1 :(得分:3)

明智地使用设计模式是一个棘手的问题,需要大量练习。

我见过很多人使用Singleton只是因为它"有点"适合他们需要做的事情。这通常会导致灾难,例如在多线程环境中,或者只是为了隐藏设计缺陷并需要稍后重新设计系统。

我说在考虑Singleton时你需要考虑一些事情:

  • 我真的只需要一个对象的实例吗?我不想隐藏一些设计缺陷吗?
  • 是否可以全局访问我的对象?

但是我说不要花太多时间在它上面:它可能并不总是最好的解决方案,但在某些情况下,这仍然是一个可接受的解决方案,除非你在在多线程环境中,您可能很少遇到问题。它主要是一种设计选择。

如果你想获得更多关于设计模式的知识,我建议this book,这几乎是关于这个主题的参考。

答案 2 :(得分:2)

只要符合以下条件,您就可以使用单身人士:

  • 您不在多线程环境中(访问单例的多个线程)
  • 处于多线程环境中并在单例内实施适当的保护
  • 单个对象未在多个动态加载的模块中定义