所以,一个使用单例模式的对象只能有一个实例。这在网站上如何工作?
问题:
- 单例对象对网站的每个客户/访问者来说都是唯一的吗?即单例对象每个客户端都获得一个实例吗?
- Web 应用程序中的对象仅持续几秒钟,因此如果两个客户端同时访问一个网站,则两个客户端都将尝试创建一个单例对象。这是否意味着会抛出一个访问者会看到的异常?我尝试谷歌搜索,但找不到直接的答案。我只是想澄清一下。
所以,一个使用单例模式的对象只能有一个实例。这在网站上如何工作?
问题:
史蒂夫,我会尽力回答你的每一个问题:
1) 对于 Web 开发,将对象限定为 Web 请求是很常见的(有时这也称为“每个请求上下文”或“每个 http 上下文”),但我们通常不将这些称为单例那个确切的原因。事实上,大多数 IOC 容器都内置了一个开箱即用的“每个 Web 请求”范围以及一个“单例”。
2) Web 应用程序有时也有真正的单例(由所有请求访问)是很常见的。如上所述,这并不完全正确,因为它将被限定在应用程序池中,并且在/如果重新启动应用程序池时会被吹走。但对于 Web 应用程序而言,这是一个单例。正如 Jigar 所提到的,有时以这种方式设置诸如日志记录等“横切关注点”。这些通常不会在每个 Web 请求中初始化,而是在 global.asax 中或依靠 IOC 容器为您执行此操作。您只需确保在执行对象创建时使用标准锁定模式之一来防止两个线程/客户端/等...同时创建对象。这是来自 Microsoft 的链接,但也有其他实现: http://msdn.microsoft.com/en-us/library/ff650316.aspx 如果您使用的是流行的 IOC 容器之一,它将为您解决这个问题(Structuremap、Windsor、Autofac、Unity、Ninject...和许多其他人)。
您需要询问您的同事他们指的是哪种方法,因为这两种方法在某些情况下都有效并且非常常见。
这完全取决于您的单例实现。在这里,我假设您将单例创建为在静态构造函数中初始化的静态字段。
理论上,根据其设置,IIS 可能会为您的应用程序创建多个进程,并且每个进程可以创建多个线程来处理请求。每个进程都有自己的单例,可以共享多个线程(和多个请求)。但是同时在一台服务器上可以有多个“单例”实例(每个进程一个)(但是,如果我理解正确,可以在 IIS 设置中禁止多个进程)。
如果您使用静态构造函数,那么将在第一次访问您的类时以线程安全的方式创建单例。请参阅C# 静态构造函数线程是否安全?
但是,尽管单例创建是线程安全的,但您仍然必须以线程安全的方式实现单例类的内部。
当您的应用程序进程存在且未重新启动时,单例将存在。应用程序进程的生命周期由 IIS 管理,因此它可以是很长的时间,也可以是很短的时间。
单例由 IIS 维护,因此单例只持续与 IIS 应用程序池一样长。一旦它被回收或 IIS 被重置,那么单例就会消失。您需要锁定单例以进行多次访问。就像您在任何其他客户端服务器应用程序中一样。
一般来说,我会尽量避免它,因为它有点违背网站本质上是无状态客户端服务器应用程序的想法。为什么不直接使用 Session 来存储任何共享数据呢?
对于记录器和共享资源,我们肯定可以在 Web 应用程序中使用单例。正如 Liam 所提到的,只要您的应用程序池没有被清除,它们就会一直存在。
为了更好地理解,请访问...http://www.oodesign.com/singleton-pattern.html
谢谢
public class SingletonContext<TContext>
where TContext: DbContext,new()
{
private static TContext _context;
private SingletonContext()
{
}
public static TContext GetInstance()
{
if (_context == null)
{
_context = new TContext();
}
return _context;
}
}