這個好像、也許、或許、大概、應該、Maybe真的可以算是傳說中的面向接口編程了吧。


                                                       這個好像、也許、或許、大概、應該、Maybe真的可以算是傳說中的面向接口編程了吧。

      假設現在有如下情況,某項目的框架結構用的是ADO.NET寫的簡單三層。且已經開始寫了一部分了。現在因為時間比較緊急,經理認為用EF寫速度會快一些,於是要求我們將訪問驅動層改成用EF寫的。

     那么,恩,好吧,我們得改了。先看一下原來DAL層和BLL層的代碼。因僅演示而已,此處只寫了一個大概思路的代碼。另外此處筆者只打算寫一個DAL層了BLL層的一個松耦合的一個漸近過程的處理。方法只寫一個。諸位見諒。主要是要有那個思路。

 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using Anmutu.OA.Model;  7 
 8 namespace Anmutu.OA.AdoNetDAL  9 { 10     public class UserAdoNetDal 11  { 12         public User AddUser(User user) 13  { 14             //在此處寫一此插入的一個SQL.會用到DBSQLHelper.using()...寫就是一個insert操作。你知道的,主要是那個思想。代碼略過。
15             return null; 16  } 17  } 18 }
訪問驅動層的代碼
 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using Anmutu.OA.AdoNetDAL;  7 using Anmutu.OA.Model;  8 
 9 namespace Anmutu.OA.BLL 10 { 11     public class UserService 12  { 13        //調用一下數據庫訪問層的方法,打個醬油。
14         private AdoNetDAL.UserAdoNetDal userAdoNetDal = new UserAdoNetDal(); 15         public User Add(User user) 16  { 17           return userAdoNetDal.AddUser(user); 18  } 19  } 20 }
邏輯層的代碼

       還好還好,DB里有的相應的表的。我們DBFirst一下,拿到EF的上下文。那么新的訪問驅動層的代碼將會是這個樣子的:

 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using Anmutu.OA.Model;  7 
 8 namespace Anmutu.OA.DAL  9 { 10     public class UserEFDal 11  { 12         public User AddUser(User user) 13  { 14             //得到的EF上下文,DBFirst不用解釋了吧。
15             AnmutuModelContainer db = new AnmutuModelContainer(); 16             //加到DB里去。
17  db.UserSet.Add(user); 18             //保存
19  db.SaveChanges(); 20             return user; 21  } 22  } 23 }
EF作為訪問驅動層時的代碼
 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using Anmutu.OA.AdoNetDAL;  7 using Anmutu.OA.DAL;//添加EF層的程序集。
 8 using Anmutu.OA.Model;  9 
10 namespace Anmutu.OA.BLL 11 { 12     public class UserService 13  { 14         #region 用EF作為訪問驅動層時的代碼。
15         private DAL.UserEFDal _userEfDal = new UserEFDal(); 16         public User AddUser(User user) 17  { 18             return _userEfDal.AddUser(user); 19  } 20         #endregion
21         #region 用ADO.NET作為訪問驅動層時的代碼
22         //private AdoNetDAL.UserAdoNetDal userAdoNetDal = new UserAdoNetDal(); 23         //public User Add(User user) 24         //{ 25         // return userAdoNetDal.AddUser(user); 26         //}
27         #endregion
28  } 29 }
修改后的邏輯層的代碼(注意對比)

 

       這樣貌似就算是修改好了。在這個小案例中。那么兩個分析一下具體的情況。現在的情況是邏輯層的的代碼,依賴與一個具體的實現,那么依賴者就必須跟着變化。就如同這里的實例名字不一樣,那么下面具體用到此實例的時候就都得改了。如果這里調用數據庫訪問層的方法的名字不一樣,同樣也是需要改動的。目前這個小案例中,修改的地方還真就不算多。但是,正如你知道的,一個項目中不可能真的只有這么一個方法的。會有很多方法。那么,是的,你得修改很多的地方了。來圖看一下,它可能是這樣。 

                           

 

       程序猿甲說,這個好辦,我們可以CTRL+F,然后選擇將相應的需要改的全部替換也就好了。

       攻城獅乙說,這個方法,固然可以,可是如果哪個地方替換錯了,就有那么一個地方名字一樣,替換錯誤了,那豈不是很麻煩么?

       程序猿丙說,我們可以依舊CTRL+F,我們選擇單個替換就好了呀,我們可以小心一點的。

       攻城獅丁說,這個方法,依舊且算可以,只是就算你很小心沒有替換錯,不是很耽誤時間的么?時間可就是金錢啊。

       那么,思路是我們就可以不讓其依賴與一個具體的實例。而是依賴與一個抽象的實例。比如讓其依賴與一個接口。用接口解除其對具體數據庫訪問的耦合。通過讓BLL層去依賴一個公共的變化很少的契約接口,依賴抽象,具體的實現在變化的時候,BLL層就不用變化了。這是對變化點的一個封裝。有點繞口且有點‘WHERE IS 南 WHERE IS 北’(筆者用此句表示不太容易理解,如果沒有了解過接口神馬的) 的感覺。簡單的說就是用一個抽象的實例,但是后面new出來的就是一個具體的了。

      那么,將修改的代碼將會是這個樣子:

 1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Linq;  5 using System.Text;  6 using System.Threading.Tasks;  7 using Anmutu.OA.Model;  8 
 9 namespace Anmutu.OA.IDAL 10 { 11     /// <summary>
12     /// 創建一個接口,約定其返回類型是User類,參數是一個user實體。 13     /// </summary>
14       interface IUserDal 15  { 16  User AddUser(User user); 17  } 18 }
DAL層接口的約束
 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using Anmutu.OA.IDAL;  7 using Anmutu.OA.Model;  8 
 9 namespace Anmutu.OA.AdoNetDAL 10 { 11     public class UserAdoNetDal:IUserDal//此處實現接口里的方法。因為接口里的方法名字也就AddUser,這里就沒有必要CTRL+SHIFT+...了。我用的是Resharper插件,也就不用點實現了。
12  { 13         public User AddUser(User user) 14  { 15             //在此處寫一此插入的一個SQL.會用到DBSQLHelper.using()...寫就是一個insert操作。
16             return null; 17  } 18  } 19 }
ADO.NET作為訪問驅動層實現接口
 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using Anmutu.OA.IDAL;  7 using Anmutu.OA.Model;  8 
 9 namespace Anmutu.OA.DAL 10 { 11     public class UserEFDal:IUserDal//這里實現接口。
12  { 13         public User AddUser(User user) 14  { 15             //得到的EF上下文,DBFirst不用解釋了吧。
16             AnmutuModelContainer db = new AnmutuModelContainer(); 17             //加到DB里去。
18  db.UserSet.Add(user); 19             //保存
20  db.SaveChanges(); 21             return user; 22  } 23  } 24 }
EF作為訪問驅動層實現接口
 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using Anmutu.OA.AdoNetDAL;  7 using Anmutu.OA.DAL;//添加EF層的程序集。
 8 using Anmutu.OA.Model;  9 
10 namespace Anmutu.OA.BLL 11 { 12     public class UserService 13  { 14         #region 實現接口后的代碼
15         //IDAL.IUserDal userDal=new UserAdoNetDal();//當要用到ADO.NET作為訪問驅動時。
16         IDAL.IUserDal  userDal=new UserEFDal();//當要用到EF作為訪問驅動時。
17         public User AddUser(User user) 18  { 19             return userDal.AddUser(user); 20  } 21         #endregion
22         #region 用EF作為訪問驅動層時的代碼。
23         //private DAL.UserEFDal _userEfDal = new UserEFDal(); 24         //public User AddUser(User user) 25         //{ 26         // return _userEfDal.AddUser(user); 27         //}
28         #endregion
29         #region 用ADO.NET作為訪問驅動層時的代碼
30         //private AdoNetDAL.UserAdoNetDal userAdoNetDal = new UserAdoNetDal(); 31         //public User Add(User user) 32         //{ 33         // return userAdoNetDal.AddUser(user); 34         //}
35         #endregion
36  } 37 }
BLL層的代碼(注意對比)

     如果要換訪問驅動層的話,請看圖:

                     

       是的,只需要在如圖的位置new一個不同的就好了。且VS會給我們提示。

       這個好像、也許、或許、大概、應該、Maybe真的可以算是傳說中的面向接口編程了吧。

 

 

       攻城獅戊說,可是我可能會有很多服務的地方都用到這個實例,那我都得改么?這樣寫很麻煩的感覺呢。

       李寧說過一句話,他說,一切皆有可能。所以,是的,也許以后園子時會多一篇叫做“這個好像、也許、或許、大概、應該、Maybe真的可以算是傳說中的簡單工廠了吧”的文章。

       筆者寫的都是很簡單的東西。歡迎指正,共同進步。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM