【问题标题】:Singleton design pattern vs static class单例设计模式与静态类
【发布时间】:2013-03-02 19:56:41
【问题描述】:

单例设计模式优于静态类以及静态类优于单例设计模式的场景有哪些?

【问题讨论】:

  • 首选方法是既不使用单例也不使用静态类。
  • @empi- 为什么,你能解释一下吗?
  • 模式讨论here和here和here和here和here和here
  • @Default:我得到的单身人士。 (正确使用的)静态类有什么不好。它们是我经常使用的扩展方法所必需的。
  • @PieterGeerkens,取决于它们是否是“静态的”。构造一个接口的实现通常会更好,即使它没有状态,这样你也可以注入它。

标签: c# design-patterns


【解决方案1】:

这并不是一个真正的非此即彼的场景。

单例是具有静态 getter 和私有构造函数的实例。它们不是静态类。

具有某些附加条件的单例是确保您只有一个类实例的一种方式。

所以第一个问题是。你是否需要一个实例,即这个东西是否有状态,第二个问题是他们进行单元测试有多困难,你是否想要一个。

例如,看看 Service Locator 模式。

【讨论】:

  • 静态类可以有状态。
  • 是的,我指的是特定于实例的状态。
【解决方案2】:

通常单例优于静态类。

单例与静态类相反:

  • 可以继承,也可以继承;
  • 可以实现接口;
  • 可以序列化;
  • 可以传递给其他类;
  • 可以处置。

如果你选择static class然后你选择concrete,没有灵活性。但是,如果您使用 singleton,则必须记住将其实例化 thread safe。

【讨论】:

  • 你不是在和一大群有影响力的人群一起游泳吗?想进一步扩展您的推理吗?
  • 不,他的所有观点都是正确的。他们都可以阻碍 DI,通常很严重
  • 我认为这种观点已经过时,您没有解释您的 5 个要点中的任何一个如何被视为一件好事。静态类是高性能的,不需要实例化并且易于单元测试
【解决方案3】:

如果您只使用类作为某些函数的容器,请使用静态类。但在大多数其他情况下,您最好使用单例设计模式,因为您可能希望重用它对象或将其实例化为非单例。

【讨论】:

  • 如果我没记错的话,静态类将在应用程序启动后加载到内存中,并一直保留到应用程序运行。虽然 Singleton 类在其第一个实例创建时被加载到内存中,并且在应用程序关闭时仍然存在。那么,您能否提出一些方案来证明一次偏好优于其他方案?
  • 一个使用单例的好场景是,您希望只有一个类的实例来(例如)在构建日志记录类时防止文件锁(将文件锁定在文件系统并且只能执行一次)...除此之外,我必须同意下面所述的comment@Dzienny。
【解决方案4】:

静态类是很难测试的专业。而且你不能将构造函数用于任何有用的东西。

在 MVC 帮助器等辅助方法中首选静态类。

您可以看到here 静态类的限制。它们只能有静态成员并且是密封的。

【讨论】:

    【解决方案5】:

    我对这次讨论的最后看法: 1. 一个对象有某种状态。状态表示对象属性的当前值。 所以,如果你想有一个场景,你想有一些可以改变的状态并且只想要一个实例,那么使用 Singleton 类。例如假设有一个日志文件要在某些成功操作或某些异常后更新。要更新这个日志文件,我们必须对其进行锁定以避免任何不一致的数据,这可以通过 Singleton 类来实现。 2. 当您不需要对象的状态并希望在应用程序启动时将类加载到内存中并一直保留到应用程序生命周期 - 使用静态类。

    【讨论】:

    • 差不多就是这样。尽管在应用程序启动时(几乎)加载到内存中更多是因为它是静态的。在 Main 中实例化一个单例也会给你。请记住关于 DI 的 cmets,即使它只是关于单元测试。单例或静态对您的伤害可能比在其他地方的帮助更大。取决于你对他们有多疯狂。
    【解决方案6】:

    您可以使用静态类为您提供不需要任何状态且不需要实例化对象的简单方法。

    使用单例意味着你只想实例化一个对象一次,你可以传递它并改变它的状态。使用单例,您还可以继承或实现接口。

    【讨论】:

      【解决方案7】:

      两者之间的主要区别在于单例可以实现接口,并且允许出于测试或运行时的原因更改其行为。静态类是静态的,虽然它可以有状态,但要彻底改变它的行为是很困难的。

      作为类的实例的单例可以实现接口,如果与期望该接口的方法一起使用,可以很容易地用不同的行为替换。

      记录是两者的常见用法。

      静态记录器不太可能记录到不同的介质(数据库、xlm 文件、文本文件、json、流、Web 服务),因为您要么必须为调用使用不同的 API,要么设置一些状态和然后让所有方法实现所有不同类型的持久性。

      单例记录器可以实现 ILog,然后如果您需要从记录到数据库切换到记录到 Web 服务,您只需使用另一个类(可能是也可能不是单例)。

      可以使用单例缓慢地远离静态类。当你意识到你永远不会改变行为时,静态类可以替换单例。

      两者本身都很难测试。但是测试使用它们的其他类可能是个问题。特别是,一个静态类——在测试和生产时,在某些方面想要稍微不同的行为(比如日志记录,或者让文件的源/目标是文件共享与共享点)并不是未知的。在这种情况下,将类设为单例可以更轻松地更改该行为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-03
        • 1970-01-01
        • 1970-01-01
        • 2012-11-26
        • 1970-01-01
        • 2011-07-30
        • 1970-01-01
        相关资源
        最近更新 更多