簡體   English   中英

這種設計模式是否有名稱,其中具體類實現了一個特定接口,該接口實現了 CRUD 操作的基本接口?

[英]Is there a name for this design pattern where a concrete class implements a specific interface which implements a base interface for CRUD operations?

我試圖把它變成一個“通用”問題,因為我在 Java 和 C# 中看到過這個問題,我假設它也在其他 OO 語言中。

我知道訪問數據並執行CRUD操作的應用程序有三個“主要”框架:

有時這些設計模式使用DAO ,有時使用DTO

在查看使用這三種設計模式之一的應用程序的教程和示例時,大多數(如果不是全部)執行以下操作:

BaseRepositoryInterface (我有時將其視為接口,有時將其視為抽象類)

interface BaseRepositoryInterface {

    findOne(integer id);

    findAll();

    create();

    read(integer id);

    update(integer id);

    delete(integer id);
}

特定存儲庫接口

interface SpecificRepositoryInterface implements BaseRepositoryInterface {

    // Just Some Examples
    specificActionNumberOne(integer id, String someString);

    specificActionNumberTwo(integer id, Object someObject);

    specificActionNumberThree(integer id, double someDouble);
}

具體存儲庫類

class ConcreteRepositoryClass implements SpecificRepositoryInterface {

    Dao myDao;
    // or
    Dto myDto;

    ConcreteRepositoryClass(Dao someDao)
    // or 
    ConcreteRepositoryClass(Dto someDto)
    {
        this.myDao = someDao;
        // or
        this.myDto = someDto;
    }

    findOne(integer id){
        // implement here ...
    }

    findAll(){
        // implement here ...
    }

    create(){
        // implement here ...
    }

    read(integer id){
        // implement here ...
    }

    update(integer id){
        // implement here ...
    }

    delete(integer id){
        // implement here ...
    }

    specificActionNumberOne(integer id, String someString){
        // implement here ...
    }

    specificActionNumberTwo(integer id, Object someObject){
        // implement here ...
    }

    specificActionNumberThree(integer id, double someDouble){
        // implement here ...
    }
}

這在所有示例中並不總是完全相同,但它們都傾向於遵循相同的格式。

鑒於此,這種設計模式有名字嗎?

假設我正在尋找名稱的這種模式是上述框架的“演示者”、“控制器”或“視圖模型”部分,只是進一步抽象,是否安全?

對我來說,這是存儲庫模式 在大多數情況下,這是在模型后面或連接到模型。 從存儲庫中,您可以為您提到的所有這些模式提供數據以進行建模。 模型可以直接存儲在存儲庫中,也可以轉換為一些 DTO 后存儲。 存儲庫通常由接口表示,以便在沒有真正連接到持久層的情況下進行測試。

我們有一個通用存儲庫模式,也有一個特定的存儲庫模式。 兩者都是正確的,各有利弊。

用於在 C# 中實現存儲庫模式:

public interface ICustomerRepository 
{        
    IEnumerable GetCustomers();        
    Customer GetCustomerByID(int customerId);        
    void InsertCustomer(Customer customer);        
    void DeleteCustomer(int customerId);        
    void UpdateCustomer(Customer customer);        
    void Save();    
}

上述接口與 EF 的實現如下所示:

public class CustomerRepository:ICustomerRepository    
{        
    private ApplicationContext context;        
 
    public CustomerRepository(ApplicationContext context)        
    {            
        this.context = context;        
    }        
    
    public IEnumerable<Customer> GetCustomers()        
    {            
        return context.Customers.ToList();        
    }        
    public Customer GetCustomerByID(int customerId)        
    {
        return context.Customers.Find(customerId);
    }
    
    public void InsertCustomer(Customer customer)
    {            
        context.Customers.Add(customer);      
    }        
    
    public void DeleteCustomer(int customerId)        
    {            
        Customer customer = context.Customers.Find(customerId);                    
        context.Customers.Remove(customer);        
    }        
    
    public void UpdateCustomer(Customer customer)        
    {            
        context.Entry(customer).State = EntityState.Modified;        
    }        
    
    public void Save()        
    {            
        context.SaveChanges();        
    }
    
}

就是這樣!

現在在 C# 中實現通用存儲庫模式

首先,為通用存儲庫創建一個接口

public interface IRepository<TEntity> where TEntity :class
{
    void Delete(TEntity entityToDelete);
    void Delete(object id);
    IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null, 
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
        string includeProperties = "");
    TEntity GetByID(object id);
    IEnumerable<TEntity> GetWithRawSql(string query, 
        params object[] parameters);
    void Insert(TEntity entity);
    void Update(TEntity entityToUpdate);
}

然后上述接口與 EF 的實現如下所示:

class BaseRepository<TEntity> : IRepository <TEntity> where TEntity : class
{
    internal ApplicationContext context;
    internal DbSet<TEntity> dbSet;

    public BaseRepository(ApplicationContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    public virtual IEnumerable<TEntity> GetWithRawSql(string query, 
        params object[] parameters)
    {
        return dbSet.SqlQuery(query, parameters).ToList();
    }

    public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        if (includeProperties != null)
        {
            foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }
        }
            

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

    public virtual TEntity GetByID(object id)
    {
        return dbSet.Find(id);
    }

    public virtual void Insert(TEntity entity)
    {
        dbSet.Add(entity);
    }

    public virtual void Delete(object id)
    {
        TEntity entityToDelete = dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(TEntity entityToDelete)
    {
        if (context.Entry(entityToDelete).State == EntityState.Detached)
        {
            dbSet.Attach(entityToDelete);
        }
        dbSet.Remove(entityToDelete);
    }

    public virtual void Update(TEntity entityToUpdate)
    {
        dbSet.Attach(entityToUpdate);
        context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}

關於存儲庫的更多信息(工作單元模式 C#):

工作單元模式 C#

為單個事務使用單獨的存儲庫可能會導致部分更新。 例如,假設您必須更新兩個不同的實體類型作為同一事務的一部分。 如果每個都使用單獨的數據庫上下文實例,一個可能成功,另一個可能失敗,確保所有存儲庫使用相同數據庫上下文(從而協調所有更新)的一種方法是使用工作單元類。

public interface IUnitOfWork
{
    IRepository<Customer> Customers { get; }
    IRepository<Order> Orders { get; }
    void Commit();
}

下面是上面 IUnitOfWork 的實現方式的代碼,

public class UnitOfWork : IUnitOfWork
{

    private ApplicationContext _dbContext;
    private BaseRepository<Customer> _customers;
    private BaseRepository<Order> _orders;

    public UnitOfWork(ApplicationContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IRepository<Customer> Customers
    {
        get
        {
            return _customers ?? 
                (_customers=new BaseRepository<Customer>(_dbContext));
        }
    }

    public IRepository<Order> Orders
    {
        get
        {
            return _orders ?? 
                (_orders=new BaseRepository<Order>(_dbContext));
        }
    }

    public void Commit()
    {
        _dbContext.SaveChanges();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM