给定的单例缓存模式的缺点

3

我正在使用给定的单例模式来在ASP.NET中缓存类对象。有人可以指出这种方法的缺点吗?

public class CacheManager
{
private static CacheManager _instance;

protected CacheManager(string key) { id = key; }
public static CacheManager getInstance(string key)
{
   if (HttpContext.Current.Cache[key] == null)
       HttpContext.Current.Cache.Insert(key, _instance = new CacheManger(key), null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(120),CacheItemPriority.Default,new CacheItemRemovedCallback(ReportRemovedCallback));

   return (CacheManager)HttpContext.Current.Cache[key];
}

private static void ReportRemovedCallback(string CacheManager, object value, CacheItemRemovedReason reason)
{            
    _instance = null;
}

public string id { get; private set; }        
public string field1 { get; set; }
public string field2 { get; set; }
public string field3 { get; set; }        
}

2
我不确定是否应该将它称为单例模式。它只是一个对非静态数据的静态包装器。这基本上就是HttpContext.Current所做的,你只是在其中添加了特定于你的应用程序的辅助方法。我对此没有任何问题。 - Yuck
它不是线程安全的,但在此之前 - 你在getInstanceReportRemovedCallback方法中试图做什么? - YavgenyP
1个回答

2
我认为你没有必要将这个类设计成单例模式。相反,我建议你为每个属性编写一个包装器,用于获取/设置其值。这样可以更容易地使用IoC容器进行注入,并提高可测试性。
目前,你的代码不是线程安全的,这可能会导致问题。

然而,有多少线程会同时使用HttpContext.Current的同一实例呢? - Yuck
我不关心当前上下文 - 那是线程本地的。问题出在这个类上。_instance 没有受到保护。 - Daniel A. White
@Yuck,为什么你认为有多个线程访问Cache对象的可能性不大?它是由应用程序域共享的,不是吗? - YavgenyP
@YavgenyP Cache 设计上是线程安全的。但实际上是否安全还要取决于提供程序。我不确定 asp.net 是如何处理它的。 - Daniel A. White
“Cache” 可能是线程安全的(我认为它是),但如果您用 if..else 语句包装对它的访问,那么它就不是线程安全的,因此这取决于他在这里处理键的方式。无论如何,对我来说,他的代码毫无意义(我不明白 _instance 做了什么,因为它似乎每次都被覆盖)。 - YavgenyP
@YavgenyP 我错过了那个。是的,它并没有被广泛使用。真糟糕。这就是为什么单例与其他单例混合在一起会很糟糕的原因。 - Daniel A. White

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接