接口隔离与存储库模式好还是坏?

时间:2014-02-04 20:10:37

标签: design-patterns domain-driven-design repository-pattern ddd-repositories

我想要使用存储库模式并创建一个通用的可恢复组件。我注意到,当我使用以下接口和基类时,我发现有时我没有实现某些方法(例如,有时我从不需要调用getAll()来检索所有对象的列表,不需要该操作在我的特定课程申请中)。

public interface IRepository<TEntity, TId>
{
   void Delete(TEntity entity);
   TEntity Get(TId id);
   IEnumerable<TEntity> GetAll();
   void Save();
   void Update(TEntity entity);
   void Create(TEntity entity);
}

我决定将胖接口分成小型接口。然后,我想出了一些可以组合在一起的实现,以准确地获得您的存储库实现所需的内容。我就是我想出的。任何人都可以就下面存在的解决方案的问题给我建议吗?

public abstract class Entity<TId> : IEntityIdentity<TId>
{
    public TId Id { get; set; }
}

public interface IEntityIdentity<TId>
{
    TId Id { get; set; }
}


public interface IDeleteRepository<TEntity, TId> where TEntity : Entity<TId>
{
    void Delete(TEntity entity);
}

public class DeleteRepository<TEntity, TId> : IDeleteRepository<TEntity, TId> where TEntity : Entity<TId>
{
    private readonly DbContext _dbContext;

    public DeleteRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }


    public void Delete(TEntity entity)
    {
        _dbContext.Set<TEntity>().Remove(entity);
    }
}

public interface ISaveRepository<TEntity, TId> where TEntity : Entity<TId>
{
    void Save(TEntity entity);
}

public class SaveRepository<TEntity, TId> : ISaveRepository<TEntity, TId> where TEntity : Entity<TId>
{

     private readonly DbContext _dbContext;

     public SaveRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }


    public void Save(TEntity entity)
    {
        _dbContext.SaveChanges();
    }
}

public interface IUpdateRepository<TEntity, TId> where TEntity : Entity<TId>
{
    void Update(TEntity entity);
}

public class UpdateRepository<TEntity, TId> : IUpdateRepository<TEntity, TId> where TEntity : Entity<TId>
{

    private readonly DbContext _dbContext;

    public UpdateRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void Update(TEntity entity)
    {
        _dbContext.Entry(entity).State = EntityState.Modified;
    }
}

public interface IGetRepository<TEntity, TId> where TEntity : Entity<TId>
{
    TEntity Get(TId id);
}

public class GetRepository<TEntity, TId> : IGetRepository<TEntity, TId> where TEntity : Entity<TId>
{
    private readonly DbContext _dbContext;

    public GetRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public TEntity Get(TId id)
    {
        return _dbContext.Set<TEntity>().Find(id);
    }
}

public interface IGetAllRepository<TEntity, TId> where TEntity : Entity<TId>
{
    IEnumerable<TEntity> GetAll();
}

public class GetAllRepository<TEntity, TId> : IGetAllRepository<TEntity, TId> where TEntity : Entity<TId>
{
    private readonly DbContext _dbContext;

    public GetAllRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IEnumerable<TEntity> GetAll()
    {
        return _dbContext.Set<TEntity>();
    }
}

public interface ICreateRepository<TEntity, TId> where TEntity : Entity<TId>
{
    void Create(TEntity entity);
}

public class CreateRepository<TEntity, TId> : ICreateRepository<TEntity, TId> where TEntity : Entity<TId>
{
    private readonly DbContext _dbContext;

    public CreateRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void Create(TEntity entity)
    {
        _dbContext.Set<TEntity>().Add(entity);
    }
}

public class RepositoryCombiner<TEntity, TId> : IGetRepository<TEntity, TId>, IGetAllRepository<TEntity, TId> where TEntity : Entity<TId>
{
    private readonly IGetRepository<TEntity, TId> _getRepository;
    private readonly IGetAllRepository<TEntity, TId> _getAllRepository;

    public RepositoryCombiner(IGetRepository<TEntity, TId> getRepository, IGetAllRepository<TEntity, TId> getAllRepository)
    {
        _getRepository = getRepository;
        _getAllRepository = getAllRepository;
    }

    public TEntity Get(TId id)
    {
       return  _getRepository.Get(id);
    }

    public IEnumerable<TEntity> GetAll()
    {
        return _getAllRepository.GetAll();
    }
}

2 个答案:

答案 0 :(得分:1)

对我而言,似乎你在思考它。如果其他任何人看到你的代码,你可能不会很清楚你想要完成什么。我建议使用可维护性而不是预先成熟的优化,这是你的目标。

如果最终某些方法从未在您的代码库中使用过,并且您在项目中完成代码,那么删除未调用的内容可能是有意义的。但就目前而言,我只是使用标准存储库模式,将您的时间和精力集中在应用程序的其他方面。

其他人是否会这样做取决于他们,但是对于检索数据,我只使用一个GetQueryable()然后根据需要执行.Single(),。first或.All() - 以及如果您的底层存储支持IQueryable相当好,您的查询可以变得更加优化。

答案 1 :(得分:0)

在真正需要时使用接口隔离原则并不是一个坏主意。但在你的情况下,我建议你使用layer super type pattern与存储库模式。一般来说,尝试使事情简单,易于阅读,理解,扩展和可维护。我见过大多数人在数据访问和存储库层中特别犯了错误。数据访问层中的代码重复在未来的变更中可能具有成本效益和繁琐。