目前我對設計模式方面了解的不多,會的設計模式五根手指頭就能數完。怎么寫好設計模式讓讀者看懂真的要講究一下技巧,不能單純的貼代碼並對代碼作解釋,我覺的《大話設計模式》就是一本講設計模式很好的書,那本書通過故事的形式講解讓人聯想思考下去。
由於水平有限,所有這篇文章沒什么講解的,只是寫一下自己使用抽象工廠實現多數據庫切換的實現過程。
例子的目的
有時候項目里使用的是ACCESS數據庫,可是突然有一天想更改成MSSQLSERVER數據庫,為了防止整站代碼重寫這種局面,可以使用抽象工廠+反射實現修改一下配置字符串就能實現ACCESS的MSSQLSERVER數據庫的切換。
實現過程
1、數據庫的建立
為了例子的講解的方便,我們就只在數據庫里建立一張表,一張顧客表(Customer)。在MSSQLSERVER數據庫里創建表的SQL語句如下:
1 use test; 2 create table Customer 3 ( 4 id int identity(1,1) primary key, 5 cName nvarchar(50), 6 cPhone nvarchar(50) 7 )
在ACCESS數據庫里也一樣創建一張Customer表,字段名一樣。
2、建立項目和類庫的准備工作
先在VS里面建立一個空的WEB應用程序,我起名為抽象工廠DEMO,之后建立數據庫的接口類庫IDAL。再建立ACCESS的數據庫訪問類庫為AccessDAL,SQLServer的數據庫訪問類庫SQLServerDAL。AccessDAL和SQLServerDAL是對IDAL接口類庫的實現,最后再建一個模型層Model。這樣准備工作就好了。大概需要的類庫和項目如下圖所示:
3、對IDAL類庫的代碼實現
在IDAL就要建立一個類,可以在類里實現對表的增刪查改等操作。這里為了做例子的方便就只實現增和查兩個接口。
建立一個類ICustomer,如下圖所示
//ICustomer.cs接口的代碼 public interface ICustomer { bool Insert(Customer customer); Customer Get(int id); }
4、對Model層代碼的實現
接口兩個類,Customer.cs 如圖:

1 Customer.cs的代碼: 2 namespace Model 3 { 4 public class Customer 5 { 6 private int _id; 7 8 public int Id 9 { 10 get { return _id; } 11 set { _id = value; } 12 } 13 private string _cName; 14 15 public string CName 16 { 17 get { return _cName; } 18 set { _cName = value; } 19 } 20 private string _cPhone; 21 22 public string CPhone 23 { 24 get { return _cPhone; } 25 set { _cPhone = value; } 26 } 27 } 28 }
5、對SQLServerDAL類庫里的代碼的實現
在SQLServerDAL里建立一個類SQLServerCustomer.cs。實現對ICustomer的接口。如圖:
SQLServerCustomer.cs的代碼 如下:

1 namespace SQLServerDAL 2 { 3 public class SQLServerCustomer : ICustomer 4 { 5 6 public bool Insert(Model.Customer customer) 7 { 8 using (SqlConnection conn = new SqlConnection("server=.;database=test;uid=sa;pwd=123456")) 9 { 10 conn.Open(); 11 using (SqlCommand cmd = conn.CreateCommand()) 12 { 13 cmd.CommandText = "insert into Customer(cName,cPhone) values('" + customer.CName + "','" + customer.CPhone + "');"; 14 cmd.ExecuteNonQuery(); 15 return true; 16 } 17 } 18 } 19 20 public Model.Customer Get(int id) 21 { 22 using (SqlConnection conn = new SqlConnection("server=.;database=test;uid=sa;pwd=123456")) 23 { 24 conn.Open(); 25 using (SqlCommand cmd = conn.CreateCommand()) 26 { 27 cmd.CommandText = "select * from Customer where id=" + id; 28 SqlDataReader dr = cmd.ExecuteReader(); 29 30 DataTable dt = new DataTable(); 31 dt.Load(dr); 32 33 Customer customer = new Customer(); 34 foreach (DataRow row in dt.Rows) 35 { 36 customer.CName = dt.Rows[0]["cName"].ToString(); 37 customer.CPhone = dt.Rows[0]["cPhone"].ToString(); 38 customer.Id = id; 39 } 40 return customer; 41 } 42 } 43 } 44 } 45 }
6、對AccessDAL類庫里的代碼實現
這里在做的時候碰到一點問題,ACCESS數據庫我放在WEB項目的DataBase文件夾里,可是在類庫里如何WEB項目里的DataBase文件夾的數據庫文件進行訪問呢?
必須要用到HttpContext.Current.Server.MapPath,在使用這句必需先引用using System.Web;
AccessCustomer.cs的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using IDAL; using System.Data; using System.Data.OleDb; using Model; namespace AccessDAL { public class AccessCustomer:ICustomer { public static string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + HttpContext.Current.Server.MapPath("/database/db1.mdb"); public bool Insert(Model.Customer customer) { using (OleDbConnection conn = new OleDbConnection(connectionString)) { conn.Open(); using (OleDbCommand cmd = conn.CreateCommand()) { cmd.CommandText = "insert into Customer(cName,cPhone) values('" + customer.CName + "','" + customer.CPhone + "');"; cmd.ExecuteNonQuery(); return true; } } } public Model.Customer Get(int id) { using (OleDbConnection conn = new OleDbConnection(connectionString)) { conn.Open(); using (OleDbCommand cmd = conn.CreateCommand()) { cmd.CommandText = "select * from Customer where id=" + id; OleDbDataReader dr = cmd.ExecuteReader(); DataTable dt = new DataTable(); dt.Load(dr); Customer customer = new Customer(); foreach (DataRow row in dt.Rows) { customer.CName = dt.Rows[0]["cName"].ToString(); customer.CPhone = dt.Rows[0]["cPhone"].ToString(); customer.Id = id; } return customer; } } } } }
7、使用反射的DataAccess類實現數據庫更改設計
這里是關鍵,通過反射
可以實現只要更改
private static readonly string AssemblyName = "AccessDAL";
private static readonly string db = "Access";
就能實現對數據庫更改的作用。
上面是使用ACCESS數據庫,如何我突然想更換成MSSQLSERVER數據庫,那么我只要把這兩句更改成
private static readonly string AssemblyName = "SQLServerDAL";
private static readonly string db = "SQLServer";
就可以了。
先在WEB項目里建一個類名為DataAccess。如圖所示:
DataAccess的代碼如下:
namespace 抽象工廠DEMO { public class DataAccess { //只需要更改這兩處就行了 //private static readonly string AssemblyName = "SQLServerDAL"; //private static readonly string db = "SQLServer"; private static readonly string AssemblyName = "AccessDAL"; private static readonly string db = "Access"; public static ICustomer CreateCustomer() { string className = AssemblyName + "." + db + "Customer"; return (ICustomer)Assembly.Load(AssemblyName).CreateInstance(className); } } }
完成這七部就可以了,建一個DEMO.ASPX頁面做一下測試,代碼如下
protected void Button1_Click(object sender, EventArgs e) { Customer customer = new Customer(); customer.CName = "demo1"; customer.CPhone = "9999"; ICustomer ic = DataAccess.CreateCustomer(); ic.Insert(customer); Response.Write("success"); } protected void Button2_Click(object sender, EventArgs e) { Customer customer = new Customer(); ICustomer ic = DataAccess.CreateCustomer(); customer = ic.Get(1); Response.Write(customer.CName); }