2

我很确定有更好的方法来做到这一点,我想得到一些反馈。

组件

我有以下(简化):

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

尝试用图表来表达这一点:

试图说明问题的类图

目标

  • 我想要 aStandardCachedItemExistenceVerifier和 aStandardNonCachedItemVerifier可以传递给 Doodad 验证器

问题/问题

在当前结构中:

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

潜在选择

也许我可以:

  • 选项 1:FillCache()甚至在 the 上实施StandardNonCacheItemVerifier并且让它什么都不做?(这似乎是一种气味)
  • 选项2:在验证器中,检查是否IItemExistenceVerifier实现了其他接口(ICacheDrivenVerifier)或其他东西,FillCache()如果是,则调用?
    • 选项3:比这两者都聪明的东西。
4

3 回答 3

2

正如Steven在他的博客中通常所说的,缓存是一个横切关注点,因此可以使用装饰器来解决。我不知道你的最终目标,但我认为它是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() );
于 2013-10-23T03:25:09.517 回答
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 );
}
于 2013-10-22T18:27:33.447 回答
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 接口时,它才会填充缓存。

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

于 2013-10-22T21:01:09.667 回答