状态很重要的对象的最佳设计模式 - 单例或静态
更具体地说,在实现依赖注入的应用程序中,对于状态很重要的类来说,最好的方法是什么。
假设我需要访问处于特定状态的对象。例如,该对象可能是在不同的线程中启动的,或者是由我无法控制的进程启动的。
.NET 中已经存在的此类对象的一个很好的示例是 HttpContext。
在这种情况下,微软决定采用静态方法,所以我只是说:
var currentObj = HttpContext.Current;
这给了我一个对象的特定实例,而不必担心它来自哪里。
静态方法的问题在于它不能很好地处理依赖注入。
另一个选项是将您的某个类配置为 IoC 容器中的单例。这意味着您可以注入它,并且根据当前的 IoC 容器配置,它将是该类的正确实例。
然而,这种方法的缺点是对象的状态重要性在代码中不再明确,通过查看它并不明显。通过使用静态类来访问和实例,可以更清楚地看出状态的重要性。也许这并不重要。
那么,有一种模式可以帮助我吗?
上下文:
对于上下文,我正在开发一个应用程序,该应用程序具有执行 IO 操作的类的许多实例。它们存在于自己的线程中。
我希望能够通过 Web 界面(即控制器)与这些对象(后台任务)进行交互。我希望能够审问它们,并操纵它们等。
更新:
抱歉,我认为我对“有状态”一词的使用有点误导。让我解释一下:
- “状态”这个词可能是错误的。我的意思是与一个我无法控制它的生命周期的对象进行通信。
- 有趣的是,我在谈论静态类时使用“有状态”。这就是为什么我给出了 HttpContext 示例,因为这正是它的作用。 Current 属性为您提供一个非常具体的实例,而不是任何新实例。
- 当我说 static 与 DI 配合不好时,我的意思是,你不能注入 Static 类。是的,我可以创建一个包装器,但我只是把问题推到别处,不是吗?
- 我应该对 Singleton 的定义更加清楚。我的意思是单例生活方式,如 IoC 容器中定义的那样。
More specifically, What's the best approach for classes where state matters, within an application which implements Dependency Injection.
Say I need access to an object that's in a particular state. For example, this object might have been initiated in a different thread, or by a process I have no control over.
A good example of an object like this that already exists in .NET is the HttpContext.
In this case, Microsoft decided to go with the Static approach, so I just say:
var currentObj = HttpContext.Current;
And this gives me a particular instance of an object without having to worry where it came from.
The problem with the Static approach is that it doesn't play very nicely with dependency injection.
The other option is to configure your certain class as a Singleton in your IoC Container. This means that you can inject it, and depending on the current IoC Container config it'll be the correct instance of the class.
However, the downfall of this approach is that the stateful importance of the object is no longer explicit in the code, it's not obvious by looking at it. With the Static class used to access and instance it's more clear that the state is important. Maybe that doesn't matter though.
So, is there a pattern that helps me out here?
Context:
For context, I'm working on an application which has many instances of a class performing IO operations. They exists within their own threads.
I want to be able to interact with those objects (background tasks) via a web interface, so a Controller. I want to be able to interrogate them, and manipulate them etc.
Update:
Sorry, I think my use of the term "stateful" is a bit misleading. let me explain some thing:
- "state" is probably the wrong word. I mean communicating with an object whereby I don't have control over it's lifecycle.
- It is funny that I use "stateful" when talking about static classes. That's why I gave the HttpContext example, as that exactly what it does. The Current property gets you a very specific instance, not any new instance.
- When I say that static doesn't play nice with DI, I meant, you can't inject Static classes. I could create a wrapper, yes, but I'm just pushing the problem elsewhere no?
- I should have been more clear about my definition of Singleton. I meant a Singleton lifestyle, as defined in an IoC Container.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我总是更喜欢单例而不是静态。事实上,我几乎从不在我自己的课程中使用静态。
I always prefer Singleton over static. In fact, I almost never use statics in my own classes.
真正的单例和静态类都很难编写自动化测试。您的意思是在运行时查找单个实例吗?这对我来说很有意义,但我不知道在 C# 中使用的正确构造。 Java 中的类似物是 JNDI。
True singletons and static classes are both very difficult to write automated tests against. Do you mean a single instance looked up at runtime? That would make sense to me but I don't know the right construct to use in C#. The analog in Java is JNDI.
两者都不是或两者都有。假设有状态依赖是线程安全的,更好的方法是围绕所述依赖至少构建一个基本的抽象层,然后将所述抽象注入到您的类中。那么单例与静态就变得非常无关紧要了。
Neither or both. Presuming the stateful dependency is thread-safe the better approach is to build at least a basic layer of abstraction around said dependency then inject said abstraction into your classes. Singleton vs static becomes pretty immaterial then.