三层架构之泛型应用
? 一說(shuō)到三層架構(gòu),我想大家都了解,這里就簡(jiǎn)單說(shuō)下,三層架構(gòu)一般包含:UI層、DAL層、BLL層,其中每層由Model實(shí)體類(lèi)來(lái)傳遞,所以Model也算是三層架構(gòu)之一了,例外為了數(shù)據(jù)庫(kù)的遷移或者更OO點(diǎn),DAL層就衍生出了IDAL接口。Model就是簡(jiǎn)單的對(duì)應(yīng)數(shù)據(jù)庫(kù)里面的類(lèi),DAL層就是主要操作數(shù)據(jù)庫(kù)的方法了,BLL這個(gè)就看業(yè)務(wù)了。而DAL層大部分的方法都是差不多,無(wú)非就是幾個(gè)Insert,Update,Delete,Select。
????? 再來(lái)說(shuō)下泛型,這個(gè)是2.0才開(kāi)始有的,算是2.0中一個(gè)非常重要的技術(shù)了,關(guān)于泛型有什么好處優(yōu)點(diǎn)就不說(shuō)了,網(wǎng)上一大堆,其實(shí)說(shuō)了也沒(méi)有什么用,大家在實(shí)踐中運(yùn)用了就知道,我覺(jué)得泛型一個(gè)最核心的地方就是,泛型封裝了類(lèi)型,把類(lèi)型的定義延遲到了客戶(hù)端,泛型又像一個(gè)類(lèi)型的模板,只要你定義了一個(gè)泛型類(lèi),就相當(dāng)于定義了N個(gè)類(lèi),每個(gè)類(lèi)的類(lèi)型不一樣而已。
????? 上面我們說(shuō)了,三層架構(gòu)中的DAL層一般包括Insert,Update,Delete,Select這幾種了,那么在泛型還沒(méi)有到來(lái)之前,我們的程序員兄弟一般是怎么做的,首先為每個(gè)實(shí)體定義一個(gè)DAL接口,比如有個(gè)User這個(gè)實(shí)體對(duì)象,那么就有一個(gè)IUserDAL這個(gè)接口以及UserDAL這個(gè)實(shí)現(xiàn)類(lèi),如果有N個(gè)實(shí)體,那么差不多就需要N個(gè)接口和實(shí)現(xiàn)類(lèi)了,而這些接口中的Insert,Update,Delete,Select的方法簽名都是類(lèi)似的,唯一的不同就是方法參數(shù)和返回值的類(lèi)型了,我們來(lái)看下基本的接口定義
1 public interface IUserDAL 2 { 3 int Insert(User model); 4 int Update(User model); 5 int Delete(int id); 6 User GetModel(int id); 7 DataTable GetList(); 8 }?
那么在一個(gè)項(xiàng)目中,像這樣的接口定義到處可見(jiàn),大部分是重復(fù)的寫(xiě)法,雖然我們有任勞任怨的代碼生成工具為我們效勞,但是從設(shè)計(jì)角度或者站在新技術(shù)的角度看,這些代碼就顯得很不優(yōu)雅,很不爽了,我想你的感覺(jué)也是這樣吧,呵呵O(∩_∩)O~。
?????? 當(dāng)泛型來(lái)臨時(shí),我們終于可以不看到那么多的重復(fù)接口的定義了,終于可以喘一口氣了,那么泛型又是怎么實(shí)現(xiàn)的呢,在實(shí)現(xiàn)之前我們回頭看下我們沒(méi)有泛型的IUserDAL的定義,其中Insert,Update方法就一個(gè)User參數(shù),類(lèi)似的其他接口也就一個(gè)參數(shù),只是類(lèi)型不是User了,可能是Order,或者其他的,在來(lái)看下GetModel返回值類(lèi)型是User,GetList也是一樣的,只是這里我們用DataTable這個(gè)萬(wàn)能的類(lèi)型來(lái)代替了,但是大家都知道DataTable這個(gè)類(lèi)型臃腫又是弱類(lèi)型的,在UI層調(diào)用的時(shí)候又不知道這個(gè)DataTable里面到底有什么字段,這個(gè)就在開(kāi)發(fā)期帶來(lái)一定的麻煩。
????? 泛型的實(shí)現(xiàn)終于上場(chǎng)了,其實(shí)很簡(jiǎn)單,不就是一對(duì)尖括號(hào)嗎,是的,只要在IUserDAL后面加對(duì)尖括號(hào),里面用一個(gè)字符代替類(lèi)型就可以了,哦,對(duì)了還要加個(gè)泛型約束呢,就是一個(gè)where,也就是說(shuō),這個(gè)泛型的類(lèi)型只能是引用的類(lèi)型,不能是值類(lèi)型,難道你的Model是一個(gè)值類(lèi)型??不可能吧,反正我是不信。那么這個(gè)泛型接口的定義就是:
1 public interface IDAL<T> where T : class 2 { 3 int Insert(T model); 4 int Update(T model); 5 int Delete(int id); 6 T GetModel(int id); 7 IList<T> GetList(); 8 }?
?哦,原來(lái)那么簡(jiǎn)單就是加個(gè)T把之前的User類(lèi)型給【換了】就可以啦,我怎么沒(méi)有想到呢,嗚嗚,那么在UserDAL這個(gè)繼承類(lèi)中就可以明確定義那個(gè)泛型的類(lèi)型了,因?yàn)槲疫@個(gè)類(lèi)就是用來(lái)實(shí)現(xiàn)User這個(gè)實(shí)體類(lèi)的(或者說(shuō)數(shù)據(jù)庫(kù)的表吧),這里,UserDAL我們就叫IUserDAL的客戶(hù)端了。代碼如下:
1 public class UserDAL : IDAL<User>2 {3 #region IDAL<User> 成員4 5 public int Insert(User model)6 {7 //coding8 }9 10 public int Update(User model) 11 { 12 //coding 13 } 14 15 public int Delete(object id) 16 { 17 //coding 18 } 19 20 public User GetModel(object id) 21 { 22 //coding 23 } 24 25 public IList<User> GetList() 26 { 27 //coding 28 } 29 30 #endregion 31 }?
好了,我們解放了DAL和IDAL,那么BLL層可以用泛型嗎,當(dāng)然可以。
?????? 我們先來(lái)說(shuō)下,不用泛型的BLL層的實(shí)現(xiàn),這里不考慮BLL的業(yè)務(wù)的話(huà),那么BLL就是單純的調(diào)用DAL的相關(guān)數(shù)據(jù)庫(kù)操作方法,也就是那個(gè)IUserDAL接口定義的方法了,一般的UserBLL代碼如下:
1 public class UserBLL2 {3 private IUserDAL dal = new UserDAL();4 5 public int Insert(User model)6 {7 return dal.Insert(model);8 }9 10 public int Update(User model) 11 { 12 return dal.Update(model); 13 } 14 public int Delete(int id) 15 { 16 return dal.Delete(id); 17 } 18 public T GetModel(int id) 19 { 20 return dal.GetModel(id); 21 } 22 public DataTable GetList() 23 { 24 return dal.GetList(); 25 } 26 }?
我想這個(gè)是最簡(jiǎn)單的BLL代碼了,而且大部分小的項(xiàng)目這樣就已經(jīng)夠了,因?yàn)闆](méi)有什么業(yè)務(wù)嘛,但是如果想這樣的代碼每個(gè)BLL都這樣謝,一個(gè)項(xiàng)目幾十個(gè)上百個(gè)也這樣寫(xiě)真的會(huì)累死人的,代碼工具雖然可以解決,但是當(dāng)我們看到那么多的重復(fù)代碼,相似的代碼,真的很心痛,難道你不覺(jué)得心痛,如果你不覺(jué)得或者也不想去改的話(huà)或者以后還是那樣寫(xiě)重復(fù)的代碼,用代碼工具幫做的話(huà),我想你的code能力也不會(huì)怎么提高,廢話(huà)一下。
????? 那么用泛型的話(huà),我們就可以為所有的BLL定義一個(gè)基類(lèi),其他類(lèi)只要繼承下,稍微的根據(jù)業(yè)務(wù)的不同增加點(diǎn)業(yè)務(wù)代碼就可以,甚至都可以不用繼承了,我們先看代碼的實(shí)現(xiàn)吧,搞這行代碼才是最好說(shuō)話(huà)的,請(qǐng)看下面代碼:
1 public class BaseBLL<T, D>2 where T : class3 where D : IDAL<T>,new ()4 {5 private D dal = new D();6 7 public virtual int Insert(T model)8 {9 return dal.Insert(model); 10 } 11 12 public virtual int Update(T model) 13 { 14 return dal.Update(model); 15 } 16 public virtual int Delete(object id) 17 { 18 return dal.Delete(id); 19 } 20 public virtual T GetModel(object id) 21 { 22 return dal.GetModel(id); 23 } 24 public virtual IList<T> GetList() 25 { 26 return dal.GetList(model); 27 } 28 }?
?? 這個(gè)也簡(jiǎn)單把,也就是把實(shí)體類(lèi)換為T(mén),把IDAL接口換為D,并定義D這個(gè)類(lèi)型的約束,也就是說(shuō)我的這個(gè)D一定是一個(gè)實(shí)現(xiàn)了IDAL<T>這個(gè)接口的,而IDAL尖括號(hào)里面的T就是BaseBLL里面的T,看到這里,相信大家都應(yīng)該明白了,如果你想實(shí)現(xiàn)UserBLL,就可以繼承BaseBLL這個(gè)基類(lèi),這里為什么把BaseBLL中的方法定義為virtual呢,原因很簡(jiǎn)單的,因?yàn)槟愕腂LL層的其他類(lèi)不可能就沒(méi)有業(yè)務(wù),不可能就是簡(jiǎn)單的調(diào)用DAL方法吧,其他的BLL類(lèi)就可以根據(jù)業(yè)務(wù)去override相關(guān)的方法了,UserBLL相應(yīng)代碼如下:
1 public class UserBLL : BaseBLL<User, UserDAL> 2 { 3 4 }?
如果UserBLL沒(méi)有任何業(yè)務(wù)的話(huà),那就不要繼承了,在UI直接用BaseBLL這個(gè)泛型類(lèi)就可以,調(diào)用也很簡(jiǎn)單
?????? BaseBLL<User> dal=new BaseBLL<User>();這樣就可以了。
?
?????? 之所以寫(xiě)這篇隨筆,是因?yàn)?8年那時(shí),我剛剛畢業(yè)投入工作后第一次看到讓我崇拜的代碼設(shè)計(jì),好像那個(gè)時(shí)候泛型也剛開(kāi)始盛行吧。
????? 最后,感謝大家的閱讀,希望大家多多支持我的博客,我是最近一個(gè)月才開(kāi)始寫(xiě)博客的,后面會(huì)有更精彩的內(nèi)容等著你來(lái)閱讀。
?
?
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
- 上一篇: php网址传值原理
- 下一篇: 漫谈IDS的虚拟化发展