在DDD領域構架系統中,為了將領域模型從領域邏輯層中和數據映射層之間解耦出來,我們引用到了Repository模式,屬於屬於泛型編程中一個比較常用的模式,尤其應用到MVC構架中更為常見,我們來簡單的介紹幾個概念:
1、在《領域驅動設計:軟件核心復雜性應對之道》,將Repository翻譯為倉儲,說明為:
一種用來封裝存儲,讀取和查找行為的機制,它模擬了一個對象集合。
2、在《企業構架模式》中,譯者對其翻譯為:資源庫,說明如下:
通過用來訪問領域對象的一個類似集合的接口,在領域與數據映射層之間進行協調
下面通過一個案例才詳細說明該解耦過程
一、新建應用程序,添加Linq To Sql,新建兩個領域模型,用會員模型(Dinner)和會議模型(RSVP),很明顯這里應該是一對多的關系,也即是說一張會議會有很多人來參與。
二、 我們將對實體的公共操作部分,提取為IRepository接口,比如常見的也就是增刪改查等方法。如下代碼:
public interface IRepository<T> where T : class
{
//改變模型中沒有更新,里面的Save就取代更新功能
IEnumerable<T> FindAll(Func<T, bool> exp);
void Add(T entity);
void Delete(T entity);
void Save();
}
三,下面我們實現一個泛型的類來具體實現上面的接口的方法。也就是實現領域模型的操作:
public class Repository<T> : IRepository<T> where T:class
{
public DataContext context;
public Repository(DataContext context)
{
this.context = context;
}
public IEnumerable<T> FindAll(Func<T, bool> exp)
{
return context.GetTable<T>().Where(exp);
}
public void Add(T entity)
{
context.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
context.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
context.SubmitChanges();
}
}
3.上面我們實現是每個實體公共的操作,但是實際中每個實體都有符合自己業務的邏輯。我們單獨定義另外一個接口,用來某些業務領域類特殊操作的約束,例如:
interface IDinnerRepository: IRepository<Dinner>
{
IList<Dinner> GetAllByDinnerId(int id);
}
4、最后該實體的Repository類實現,注意要同時繼承它的接口約束和Repository<T>類,如下:
public class DinnerRepository : Repository<Dinner>, IDinnerRepository
{
public DinnerRepository(DataContext dc)
: base(dc)
{ }
public IList<Dinner> GetAllByBookId(int id)
{
var listDinner = from c in context.GetTable<Dinner>()
where c.DinnerID == id
select c;
return listDinner.ToList();
}
}
基本思路就這樣了,在我們使用的時候,需要幾個擴展類,在定義領域模型責任接口,在實現領域對象業務領域的擴展,實現類就要同時繼承基類和約束接口了。