C#类设计:一些具有缓存功能的类的策略模式?

时间:2013-10-22 17:51:13

标签: c# class design-patterns

我很确定有更好的方法可以做到这一点,我希望得到一些反馈。

组件

我有以下(简化):

  • Item,实现IItem
  • 一个Doodad,其中包含List<IItem>
  • IItemExistenceVerifier接口,需要bool ItemExists(string ItemToCheck)
  • StandardCachedItemExistenceVerifier,其中包含FillCache(List<IITem> items)
  • DoodadValidator接受IItemExitenceVerifier并且Validate方法为Doodad项目列表中的每个项目调用ItemExists(item)

尝试在图表中表达:

A class diagram attempting to illustrate the problem

目标

  • 我想要一个StandardCachedItemExistenceVerifierStandardNonCachedItemVerifier我可以传递给Doodad验证器

问题/问题

在当前结构中:

  • 验证器将收到IItemExistenceVerifier,并且不知道它是否使用缓存。存在验证程序将提前新建,因此我无法创建新的验证程序并在构造函数中传递项目。
  • 我无法始终将FillCache()作为验证的一部分,因为界面不需要它。

潜在选项

也许我可以:

  • 选项1:甚至在FillCache()上实施StandardNonCacheItemVerifier并让它什么都不做? (这似乎是一种气味)
  • 选项2:在验证程序中,检查IItemExistenceVerifier是否实现了其他某个界面(ICacheDrivenVerifier)或其他内容,然后调用FillCache()(如果有)?
    • 选项3:比这两者更聪明的东西。

3 个答案:

答案 0 :(得分:2)

正如Steven blog中{{3}}所说,缓存是一个贯穿各领域的问题,因此可以使用装饰器来解决。我不知道你的最终目标,但我认为它是if the cache exists, use cache. If not, get from query and put in cache

你需要的是将操作分成2个类,一个类来检索对象,另一个类来验证。

以下是一个例子:

public interface IItemRetriever{
    public IEnumerable<IItem> GetList();
}

public class StandardItemRetriever : IItemRetriever{
    public IEnumerable<IItem> GetList(){
        // returning the data
    }
}

public class CachedStandardItemRetriever : IItemRetriever{
    public CachedStandardItemRetriever(StandardItemRetriever standardItemRetriever){
        // property assignment
    }

    IEnumerable<IItem> items;
    public IEnumerable<IItem> GetList(){
        if(items == null || !items.Any())
        {
            items = this.standardItemRetriever.GetList();
        }
        return items;
    }
}

public class StandardItemExistanceVerifier{
    public StandardItemExistanceVerifier(IItemRetriever iItemRetriever){
        // property assignment
    }
}

这样,您的验证者只需要IItemRetriever注入,其中可以是标准的或缓存的。

new StandardItemExistanceVerifier( new CachedStandardItemRetriever(new StandardItemRetriever()) );
new StandardItemExistanceVerifier( new StandardItemRetriever() );

答案 1 :(得分:0)

  

验证器将收到IItemExistenceVerifier,并且不知道它是否使用缓存。

这就是为什么你有一个界面 - 隐藏实现细节。没关系。

DoodadValidator不应该关心缓存,以及IItemExistenceVerifier。只有StandardCachedItemExistenceVerifier才能像任何其他验证程序一样工作,但有缓存。

怎么做?方法ItemExists应该如下工作:

public bool ItemExists( string itemToCheck )
{
    // Firstly checking if the item is already in the cache
    if( this.cache.ItemExists( itemToCheck ) )
    {
        return true;
    }

    // Trying to load the item into the cache. If it doesn't exist, returning false
    return this.cache.tryLoadItem( itemToCheck );
}

答案 2 :(得分:0)

以下是一个答案(我想?),如果我没有看到更好的答案,我会选择这个答案:

  • 我创建了一个界面ICacheFillable<T>
  • 我设置验证程序以实现ICacheFillable<string>
  • 在我的处理器中,在我遍历所有项目以验证它们之前,我调用FillCacheForVerifier()方法。
  • FillCacheForVerifier()方法如下所示:

    private void FillItemVerifierCache()
    {
        // Attempt to cast the verifier 
        var potentiallyCacheableVerifier =
            _DoodadValidator.ItemVerifier as ICacheFillable<string>;
    
        // if the item is cacheable 
        if (potentiallyCacheableVerifier != null)
        {
            // get all of the items into a list of strings
            var cacheItems = from x in _doodad.Items select x.StringProperty;
    
            // fill the cache with the items
            potentiallyCacheableVerifier.FillCache(cacheItems);
        }
    
    }
    

因此,最终结果是,只有传入的项目符合其选择的ICacheFillable接口时,它才会填充缓存。

如果这不是一个好主意(并且我绝不相信),那么希望它至少可以帮助说明我认为我的问题是什么。