具有通用存储库的装饰器设计模式



我一直在研究装饰器设计模式(我是设计模式的新手)。

我已经在使用baseerepository模式。但是我也想使用一些缓存

下面的示例只是一个转储示例。

所以我有genericrepository接口及其实现

public interface IGenericRepository<T> where T : class
{
T GetById(int id);
IEnumerable<T> GetAll();
Task<T> GetByIdAsync(int id);
T Add(T entity);
void AddRange(IEnumerable<T> entities);
Task<T> AddAsync(T entity);
Task AddRangeAsync(IEnumerable<T> entities);
void Remove(T entity);
void RemoveRange(IEnumerable<T> entities);
int SaveChanges();
Task<int> SaveChangesAsync();
}
然后我创建了一个自定义存储库,例如IBlogRepository
public interface IBlogRepository : IBaseRepository<Blog>
{
public Task<Blog> GetBlogsByCreatorAsync(int creatorId);
}

BlogRepository的实现

public class BlogRepository : BaseRepository<Blog>, IBlogRepository
{
public BlogRepository(DbContext db) : base(db)
{
}
public Task<Blog> GetBlogsByCreatorAsync(int creatorId) =>
db.Blogs.Where(b => b.CreatorId == creatorId)
.ToListAsync();
}

我觉得这很酷,然后我意识到我需要提高我的"速度"。我开始使用IMemoryCache,但在仓库代码如下。

public class BlogRepository : BaseRepository<Blog>, IBlogRepository
{
public BlogRepository(DbContext db, IMemoryCache cache) : base(db)
{
}
public Task<Blog> GetBlogsByCreatorAsync(int creatorId) 
{
// if in cache else go to db
} 

}

然后我遇到了装饰图案,我想为什么不呢,我开始使用它,但我现在很挣扎。我创建了CachedBlogRepository也就是实现IBlogRepository,但当我要求VS实现所有接口方法…

public class CachedBlogRepository : IBlogRepository
{
//All BaseRepository methods appeared here...
//But I want cache only the GetBlogsByCreatorAsync method
}

那么这里的最佳实践是什么呢?是我遗漏了什么还是我做错了什么?

看起来这是一个可以使用CachedRepository模式的地方。

我强烈建议你阅读这篇关于在asp.net Core中构建cacherepository的漂亮文章

所以在应用CachedRepository模式之后会是这样的:

public List<Blog> GetBlogsByCreatorAsync(int id)
{
string key = MyModelCacheKey + "-" + id;
return _cache.GetOrCreate(key, entry =>
{
entry.SetOptions(cacheOptions);
return _repository.GetBlogsByCreatorAsync(id);
});
}

你可以在gihub

看到源代码

首先我不明白这部分:

BlogRepository: BaseRepository, bloblogrepository

应该是:

BlogRepository: bloblogrepository ?

现在,当它出现在Decorator Pattern时,我会这样做:

public interface IGenericRepository<T> where T : class
{
T GetById(int id);
IEnumerable<T> GetAll();
Task<T> GetByIdAsync(int id);

T Add(T entity);
void AddRange(IEnumerable<T> entities);
Task<T> AddAsync(T entity);
Task AddRangeAsync(IEnumerable<T> entities);

void Remove(T entity);
void RemoveRange(IEnumerable<T> entities);

int SaveChanges();
Task<int> SaveChangesAsync()
}

(组件)

public class BlogRepository : BaseRepository<Blog>, IBlogRepository
{
public BlogRepository(DbContext db) : base(db)
{
}
public Task<Blog> GetBlogsByCreatorAsync(int creatorId) =>
db.Blogs.Where(b => b.CreatorId == creatorId)
.ToListAsync();
}

(具体组件)

abstract class Decorator :  IGenericRepository<T>
{
protected IGenerecRepository _repository;
public Decorator( IGenerecRepository repository)
{
this._repository = repository;
}
public override Task<Blog> GetBlogsByCreatorAsync()
{
if (this._repository != null)
{
return this._repository.GetBlogsByCreatorAsync();
}
else
{
return string.Empty;
}
}
}

(基地Decorator)

class CacheDecorator : Decorator
{
public CacheDecorator(IGenericRepository repo) : base(repo)
{
}
public override Task<Blog> GetBlogsByCreatorAsync()
{
//cache behavior
}
}

Uasage:

BlogRepository _basicRepo = new BlogRepository();
CacheDecorator _cacheDecorator = new CacheDecorator(_basicRepo);
_cacheDecorator.GetBlogsByCreatorAsync(creatorId);

Decorator Pattern将行为添加到主基本行为中。它需要一个包装(基本组件)来包装它周围的新行为。

最新更新