替代单例模式用于唯一资源的方案

4

我一直反复阅读,发现有很多原因要避免使用单例模式。我想知道如何正确处理一个类代表唯一系统资源的情况。例如,使用SDL的AudioOutput类。由于SDL_OpenAudio一次只能打开一次,拥有多个此类型的对象毫无意义,我认为防止意外创建多个对象实际上是好的。

只是想知道经验丰富的程序员对此有什么看法,我是否错过了其他选项?


2
拥有多个标准输出是没有意义的。 - Kerrek SB
3个回答

9
Singleton模式的一个问题是,它的使用往往会破坏控制反转原则(或者在SOLID中称为依赖倒置)。
Singleton不仅防止创建多个对象,而且还使得这个对象可以从代码的任何地方访问。这很糟糕,因为如果你决定改变对象的创建/访问方式,那么你需要改变所有期望通过静态SingletonClass.GetInstance()访问它的代码位置。
此外,在实施单元测试时,通常需要使用模拟对象而不是真实对象。在你的情况下,如果你想要对某个模块进行单元测试,并且该模块通过SingletonClass.GetInstance()访问了真实的音频输出,那么用一个存根来替换真实的音频输出将变得非常困难。
另一方面,如果你的模块通过依赖注入获得音频输出对象(例如,作为传递给构造函数的参数),那么在测试时,你可以注入一个实现相同接口的存根,而不是真正的音频输出对象。
当你注入这种对象时,你可以使用单例模式来确保一次只有一个实例。主要的重点是底层代码不应该关心可以有多少个对象,或者它们如何获取 - 它只处理被注入的内容。
因此,总的来说,如果你认为需要,可以使用单例模式,但不要将其作为全局状态访问。

3

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

我看到很多人仅仅因为Singleton“有点”符合他们需要做的事情就使用它。这通常会导致灾难,例如在多线程环境下,或者只是因为它意味着隐藏了设计缺陷并且后来需要完全重构系统。

我认为,在考虑Singleton时,您需要思考几件事情:

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

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

如果您想获得更多有关设计模式的知识,我建议阅读this book,这几乎是该主题的参考书。


谢谢这本书,希望它能帮助我更好地理解面向对象编程 :) - Unimportant

2
只要符合以下条件,单例模式就可以使用:
  • 不在多线程环境中(多个线程同时访问单例)
  • 在多线程环境中且实现了单例的保护机制
  • 单例对象没有在多于一个动态加载模块中定义

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接