在项目中拥有大量单例类是不是很好的编程?

时间:2010-01-17 06:54:45

标签: c++ singleton

我在项目中有一些应该只创建一次的类。

最好的方法是什么?,

  1. 可以将它们创建为静态对象。
  2. 可以创建为单身人士
  3. 可以创建为全球。
  4. 实现此目的的最佳设计模式是什么?

    我正在考虑将所有类创建为单例,但这会产生很多单例。拥有大量单身人士是一种很好的编程实践吗?

    使用单身人士的利弊是什么?

9 个答案:

答案 0 :(得分:16)

看一下Steve Yegge的博客文章 - Singleton Considered Stupid

答案 1 :(得分:6)

如果他们只需要创建一次,那并不强制他们应该是单身。

  • 如果X是单身,那暗示有一个实例。
  • 如果X有一个实例,那并不意味着它应该是一个单例。

如果需要,则只使用一个单例实例,并且可以全局访问。在你的情况下,只需要一个是不够的理由。全球化是坏的,单身人士是美化全球化的。

大多数情况下,您不需要它们。你会在糟糕的代码中看到很多因为心态:我只需要一个,这必须意味着我应该让它成为单身人士! (错误)例如,我已经完成了迄今为止我所做过的最强大的游戏引擎的技术设计。它有2个单体,用于记忆和线程。一个非常大的项目,我只有两个!

更多背景信息有助于我们为您提供更好的信息。

答案 2 :(得分:5)

我建议您查看Google的MiškoHevery所做的一些视频和文章。首先是视频:"Clean Code Talks: Global State and Singletons"his blog

一般的共识是,Singletons在少数情况下是可以的,例如日志记录,但在大多数其他情况下,您希望使用依赖注入。单例使得测试代码变得更加困难,并且它们隐藏了依赖关系,因此无法轻易地实例化您的类。

答案 3 :(得分:4)

单身人士有一些问题 - 他们很难测试,难以替换,也很难扩展。通常有更好的方法。

答案 4 :(得分:3)

我对单身人士最喜欢的一篇文章是MiškoHevery的Singletons are Pathological Liars。从本质上讲,他们鼓励“隐藏”的行为很难学习和测试。

答案 5 :(得分:1)

单身人士实际上是全球状态。如果你要创造大量的单身人士,那么你将会创造出许多全球化的状态,只是不一定会看起来像全球状态。

这使得构建单元测试,提供模拟类和重用代码变得很困难,因为它非常容易 将当前状态耦合到一个函数。即函数foo仅在class X位于state Z时有效,否则无效。

正确构建线程安全单例也存在问题。

单身人士可以很好地协调对资源的访问,特别是那些没有太多状态且构建成本高的资源。

那么为什么你认为你需要很多的单身人士?如果您询问自己的问题域以及遇到的问题,可能会得到更好的回复。

答案 6 :(得分:1)

有些项目实际上无法避免使用全局变量。各种服务定位器或依赖注入框架仍然依赖于全局(不总是静态变量,但总是某种全局的)对象存储。

然而,单身是一个问题的迹象:

  • 首先,作为规范模式的单例与接口和抽象不相符。它可以修复 - 通过工厂访问它。
  • 更糟糕的是,单身人士缺乏灵活性 - 他们没有任何方法来识别超出其类型的对象。 (好吧,在C ++中,他们通过模板完成,但这是一个不同的故事)。从这个意义上讲,它们实际上比静态变量更糟糕。从长远来看,它可以使用一个可以访问许多相同类型实例的框架来获得回报。
  • 最重要的是,许多单身人士意味着物体之间存在许多遥远的关系。这意味着您的系统可能比它需要的更复杂,并且开发,测试和管理将更加困难。简单地切换到定位器或DI将无济于事,这是基本设计原则的问题。

答案 7 :(得分:0)

在编程中没有银子弹。让每个班级成为单身人士都不会神奇地使你的代码变得“更好”。单身人士是解决特定问题的工具,我更多地研究单身人士。

答案 8 :(得分:0)

在项目中使用单例模式应该是一个经过深思熟虑和谨慎的设计决策,因为它是一条单向轨道,回溯范围很小。我实际上在我的一个项目中使用它来处理多线程环境中的商业产品并面临许多问题。但这并不意味着它是一种不可触碰的模式。关键是任何可以通过单独实现的东西都可以在没有它的情况下实现,减少了麻烦和复杂性。有关这方面的更多信息,您可以追踪this question几个月前我问过的问题。它有趣的链接和对单例模式的洞察