【问题标题】:Is performance a sufficient reason for having a singleton or static class?性能是拥有单例类或静态类的充分理由吗?
【发布时间】:2010-10-13 15:04:03
【问题描述】:

我有一个我认为不应该是单例或静态类的类。它有状态,尽管状态 可以 由消费者共享。当存在共享状态时,我喜欢远离单例,但我听到的论点是,我将通过在任何给定时间只存在一个对象实例来获得性能优势。

在我的特定情况下,与此对象相关联的数据并不多——两个字典(最多)每个字典中有 150 个条目。

在什么时候——如果有的话——性能论点有什么价值?

仅供参考 - 我正在使用 .NET。

谢谢!

【问题讨论】:

  • 这个论点有没有提到为什么单例在任何情况下都会更快?否则,以您的代码为基础似乎是一种信念的飞跃。
  • 免责声明 - 我不相信这个论点(因此提出了问题),但是:1.)如果只能存在 1 个实例,内存占用会更小,2.)实例化新实例的开销如果对象只构造一次,则实例会减少。
  • 创建新对象的成本是多少。支持性能声明必须非常昂贵

标签: .net performance oop static singleton


【解决方案1】:

没有。性能论点没有任何价值。

在假设您有性能问题之前,您应该进行基准测试并确认/识别性能问题。 10 次中有 9 次不是你想的那样。

如果需要单例,那就是。

【讨论】:

  • 是的,闻起来像是过早的优化。
  • 但几乎从不需要单例。大多数支持单例的论点都没有任何价值。 ;)(我能想到的唯一一个你绝对想强制执行“只有一个实例”的事情是在驱动程序开发和类似的情况下,直接映射到硬件。
【解决方案2】:

单例模式的存在主要是为了让你指定你只需要一个类的实例。静态类通常用于提供无状态行为。你所描述的似乎并不真正适合任何一个类别。我会研究使用缓存而不是单例模式来提高代码的性能。当然,你的缓存可能是一个单例,但对于缓存来说,它是有意义的。

当然,如果你的对象是一个缓存,那么我只是把自己说成一个圈子。

【讨论】:

  • LOL “当然,如果你的对象是缓存,那我只是把自己说成一个圈子。”
【解决方案3】:

您不应该出于性能原因考虑创建单例(或静态类)。

您要么需要按设计使其成为单例,要么不需要。如果您的类应该存在多个实例并且彼此不同,那么您不能使用单例。

【讨论】:

    【解决方案4】:

    我不认为性能是一个非常有力的论据,无论是支持还是反对使用单例模式。这是一个设计问题,使用单例是否有意义:

    如果您只需要对象的一个​​实例,请使用单例。

    如果您需要多个实例,请不要。

    【讨论】:

    • 如果您只需要一个实例,请只声明一个实例。如果声明两个实例会导致世界崩溃,请将其设为单例。
    • @jalf - 是的,我们都听说过 signleton 作为反模式的观点。我的建议是假设你对单身人士没有一些荒谬的偏见。
    【解决方案5】:

    您应该仅在概念上只有一个对象实例的情况下使用 Singleton,而不是人为地将开发人员限制为一个实例。如果可能有两个实例,那么它不应该是单例。

    如果是前者,并且存在与对象关联的状态,那么如果与初始化相关的成本很高,并且有可能永远不会使用该类,或者有理由推迟初始化,那么单例是有用的.在这种情况下,单例是好的。另一种方法是使用静态类,当上述情况不适用时,您应该使用它。

    【讨论】:

      【解决方案6】:

      如果构建成本很高,那么您可能更适合返回公共实例的Abstract Factory 模式。 Singleton 的名声不好,尤其是在 TDD 人群中,但实际上 AF 和 Singleton 可以做同样的事情(AF 可以做的更多,但这是另一回事)。

      既然你的成本不高,那可能就无所谓了。

      【讨论】:

        【解决方案7】:

        通常,单例会抑制性能,比什么都重要。这意味着您必须在多线程应用程序中将类包装在锁和同步中。如果不使用单例或全局变量,这可能是可以避免的。

        所以单例可能会更慢,但我想不出任何情况下它会更快。

        如果您希望您的应用程序共享一个对象的单个实例,则传递对该对象的引用。这也让您可以灵活地在以后更改设计,因为事实证明,出于缓存或并发原因,使用多个单独的实例实际上会更快。

        关于性能,要记住的最重要的一点是它很难预测。不管你猜你的瓶颈是什么,你几乎肯定是错的。因此,确保良好性能的最佳方法是让您的程序易于修改。单身人士在那里对你不利。一旦你有了一个单例,就几乎不可能删除。即使多个实例的性能会更好,即使使用局部变量而不是全局单例会提高缓存的使用率,您也只能使用该类的一个通用实例。

        【讨论】:

        • 好吧,吹毛求疵,如果您不需要遵循多个参考,单身可能会更快,但实际上这不应该影响任何事情。
        • 为什么会更快?因为每次方法调用都必须少复制一个引用?我想,但那时我们基本上是在谈论一个周期,在今天的 CPU 上甚至可能不是这样。或者还有其他我没有发现的开销?
        • 传递引用是提供您所说的灵活性的一种丑陋方式。您可以从静态 CreateInstance 方法中获得完全相同的灵活性。它要么返回一个单例(延迟初始化,如果您愿意),或者稍后您可以更改它以创建任意数量的实例。
        • 是的,这是另一种选择。有很多方法可以避免单例并允许实现细节的灵活性。但是不管你怎么做,只要你远离单例,你可能做得还不错。 :)
        猜你喜欢
        • 1970-01-01
        • 2016-03-11
        • 1970-01-01
        • 2012-11-15
        • 1970-01-01
        • 1970-01-01
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多