【问题标题】:Best design pattern for objects where state is important - Singleton or Static状态很重要的对象的最佳设计模式 - 单例或静态
【发布时间】:2011-03-08 03:03:39
【问题描述】:

更具体地说,在实现依赖注入的应用程序中,对于状态很重要的类,最好的方法是什么。

假设我需要访问处于特定状态的对象。例如,这个对象可能是在不同的线程中启动的,或者是由我无法控制的进程启动的。

.NET 中已经存在的此类对象的一个​​很好的例子是 HttpContext。

在这种情况下,微软决定采用静态方法,所以我只想说:

var currentObj = HttpContext.Current;

这给了我一个特定的对象实例,而不必担心它来自哪里。

静态方法的问题在于它不能很好地与依赖注入配合使用。

另一个选项是将您的特定类配置为 IoC 容器中的单例。这意味着您可以注入它,并且根据当前的 IoC 容器配置,它将是该类的正确实例。

但是,这种方法的缺点是对象的状态重要性在代码中不再明确,通过查看它并不明显。使用用于访问和实例化的静态类,更清楚地表明状态很重要。不过也许这并不重要。

那么,这里有什么模式可以帮助我吗?

上下文:

对于上下文,我正在开发一个应用程序,它有许多执行 IO 操作的类实例。它们存在于自己的线程中。

我希望能够通过 Web 界面(即控制器)与这些对象(后台任务)进行交互。我希望能够审问他们,操纵他们等等。

更新:

抱歉,我认为我对“有状态”一词的使用有点误导。让我解释一下:

  1. “状态”可能是错误的词。我的意思是与我无法控制其生命周期的对象进行通信。
  2. 有趣的是,我在谈论静态类时使用“有状态”。这就是我给出 HttpContext 示例的原因,因为它正是这样做的。 Current 属性为您提供了一个非常具体的实例,而不是任何新实例。
  3. 当我说静态与 DI 不兼容时,我的意思是,你不能注入静态类。我可以创建一个包装器,是的,但我只是将问题推到其他地方不是吗?
  4. 我应该更清楚我对 Singleton 的定义。我指的是 IoC 容器中定义的单例生活方式。

【问题讨论】:

  • “静态方法的问题在于它不能很好地与依赖注入配合使用。” - 你想玩什么?看来您也可以想到一个池而不是单例。
  • “对象的状态重要性在代码中不再明确”是什么意思?您的问题似乎太抽象而无法回答。不是所有重要的对象都是有状态的吗?具有讽刺意味的是(对我来说,无论如何)您将有状态的术语应用于静态方法。
  • Singleton 的 get 访问器本身是一个静态属性(或方法,如果您愿意)不是吗?所以这不仅仅是静态与单例的问题,更多的是关于你的方法......
  • @Mark:大概他可以在他的 DI 框架中简单地将项目标记为单例,从而将相同的实例返回给每个人。所以,不,不一定会涉及静态属性。
  • @JohnOpincar:“大概他可以简单地将项目标记为他的 DI 框架中的单例,从而将相同的实例返回给每个人” - 完全正确,约翰,谢谢

标签: c# design-patterns static dependency-injection singleton


【解决方案1】:

我总是更喜欢单例而不是静态。事实上,我几乎从不在自己的类中使用静态。

【讨论】:

  • 酷,谢谢约翰。我想我是在问这个问题,看看我是否错过了一些更大的第三个选项。我猜想使用 IoC 容器控制器 Singleton 的关键。欢呼
【解决方案2】:

真正的单例和静态类都很难编写自动化测试。您的意思是在运行时查找单个实例吗?这对我来说很有意义,但我不知道在 C# 中使用正确的构造。 Java 中的类比是 JNDI。

【讨论】:

    【解决方案3】:

    两者都不是。假设有状态依赖是线程安全的,更好的方法是围绕所述依赖构建至少一个基本抽象层,然后将所述抽象注入到你的类中。那么单例与静态就变得无关紧要了。

    【讨论】:

    • 你不会把同样的问题转移到另一个班级吗?
    • 并非如此。您的类具有构造函数依赖项,并且并不真正关心所述依赖项的来源。可以根据需要轻松使用实例类,或者使用 IoC 封装单例或静态引用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    相关资源
    最近更新 更多