2010年4月3日使用工廠(chǎng)方法模式實(shí)現(xiàn)多數(shù)據(jù)庫(kù)WinForm手機(jī)號(hào)碼查詢(xún)器(附源碼)
關(guān)于工廠(chǎng)模式
先講一下簡(jiǎn)單工廠(chǎng)模式、工廠(chǎng)方法模式、抽象工廠(chǎng)模式的東西:
- 簡(jiǎn)單工廠(chǎng)模式(Simple Factory Pattern):工廠(chǎng)類(lèi)中包含了必要的邏輯判斷,根據(jù)客戶(hù)端的選擇條件動(dòng)態(tài)實(shí)例化相關(guān)類(lèi),也就是說(shuō)產(chǎn)品的創(chuàng)建邏輯集中于一個(gè)工廠(chǎng)類(lèi),客戶(hù)端只需要傳遞不同的參數(shù)給工廠(chǎng),這時(shí)情況是:一個(gè)工廠(chǎng)創(chuàng)建一個(gè)產(chǎn)品,所有的具體工廠(chǎng)繼承自一個(gè)抽象工廠(chǎng);對(duì)于客戶(hù)端來(lái)說(shuō),不存在與具體產(chǎn)品的依賴(lài);
- 工廠(chǎng)方法模式(Factory Method Pattern):提前定義用于創(chuàng)建對(duì)象的接口,讓子類(lèi)決定實(shí)例化具體的某一個(gè)類(lèi),即在工廠(chǎng)和產(chǎn)品中間增加接口,工廠(chǎng)不再負(fù)責(zé)產(chǎn)品的創(chuàng)建,由接口針對(duì)不同條件返回具體的類(lèi)實(shí)例,由具體類(lèi)實(shí)例去實(shí)現(xiàn);
- 抽象工廠(chǎng)模式(Abstract Factory Pattern):提供一個(gè)創(chuàng)建一系統(tǒng)或相互依賴(lài)對(duì)象的接口,不需要指定具體類(lèi)。抽象工廠(chǎng)正如其名字所說(shuō),它抽象的是工廠(chǎng)接口,因此它面向的是多個(gè)平等等級(jí)結(jié)構(gòu),其建立對(duì)象的原則是以功能相似的對(duì)象為單位劃分需要建立的對(duì)象。
簡(jiǎn)單工廠(chǎng)并不屬于23種基本設(shè)計(jì)模式中,它是抽象工廠(chǎng)模式的一個(gè)特例;抽象工廠(chǎng)與工廠(chǎng)方法區(qū)別在于它們抽象的對(duì)象不同:工廠(chǎng)方法針對(duì)產(chǎn)品進(jìn)行抽象,而抽象工廠(chǎng)抽象針對(duì)工廠(chǎng)。因此可以認(rèn)為工廠(chǎng)方法是抽象工廠(chǎng)的一種極端情況,工廠(chǎng)方法模式用來(lái)創(chuàng)建一個(gè)產(chǎn)品的等級(jí)結(jié)構(gòu),它一般只有一個(gè)方法,創(chuàng)建一種產(chǎn)品;而抽象工廠(chǎng)是用來(lái)創(chuàng)建多個(gè)產(chǎn)品的等級(jí)結(jié)構(gòu),一般有多個(gè)方法,創(chuàng)建一系列產(chǎn)品。
手機(jī)號(hào)碼查詢(xún)?cè)O(shè)計(jì)
此程序主要功能就是根據(jù)手機(jī)號(hào)碼段查詢(xún)相應(yīng)的號(hào)碼歸屬地。數(shù)據(jù)來(lái)自網(wǎng)絡(luò),數(shù)據(jù)表結(jié)構(gòu)如下
數(shù)據(jù)記錄超過(guò)17萬(wàn)條
這里我使用了Sqlite數(shù)據(jù)庫(kù),將此數(shù)據(jù)庫(kù)文件轉(zhuǎn)換為Sqlite數(shù)據(jù)庫(kù)文件。
主程序界面設(shè)計(jì)如下:
業(yè)務(wù)邏輯分析
主程序調(diào)用業(yè)務(wù)邏輯層BLL,BLL使用抽象工廠(chǎng)DALFactory方法,DALFactory創(chuàng)建DAO實(shí)例對(duì)象,接口層IDAL定義數(shù)據(jù)操作接口方法,由數(shù)據(jù)訪(fǎng)問(wèn)層通過(guò)各自的公用數(shù)據(jù)操作類(lèi)庫(kù)進(jìn)行讀寫(xiě)數(shù)據(jù)庫(kù),實(shí)現(xiàn)對(duì)實(shí)體類(lèi)Model的訪(fǎng)問(wèn)。
解決方案文件列表如圖
其中DBUtility為公共數(shù)據(jù)訪(fǎng)問(wèn)類(lèi)庫(kù)。三個(gè)數(shù)據(jù)訪(fǎng)問(wèn)層SQLServerDAL、SqliteDAL和OleDAL分別對(duì)應(yīng)Sql Server、Sqlite、Access數(shù)據(jù)庫(kù)。這里我正在使用的是SqliteDAL。
具體實(shí)現(xiàn)
建立實(shí)體類(lèi)進(jìn)行對(duì)象封裝
App.config定義選用的DAL及數(shù)據(jù)庫(kù)連接信息
代碼
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!--<add key="DAL" value="CuteMobileSearch.SQLServerDAL"/>
<add key="DAL" value="CuteMobileSearch.SQLiteDAL"/>
<add key="DAL" value="CuteMobileSearch.OleDAL"/>-->
<!--當(dāng)前使用DAL;可選以上三者之一,分別對(duì)應(yīng)Sql Server、Sqlite、Access數(shù)據(jù)庫(kù)-->
<add key="DAL" value="CuteMobileSearch.SQLiteDAL"/>
<add key="SqlConn" value="server=.;database=CuteMobileDB;uid=sa;pwd=123456"/>
<add key="SqliteFile" value="/App_Data/db.db"/>
<add key="OleFile" value="/App_Data/mobile.mdb"/>
</appSettings>
</configuration>
SqlConnStr.cs文件用于獲得相應(yīng)的連接字符串ConnectionString
代碼
/// <summary>
/// 獲得連接字符串ConnectingString
/// </summary>
public static class SqlConnString
{
public static string ReturnConnString()
{
string _appPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//當(dāng)前程序路徑
string _dal = System.Configuration.ConfigurationManager.AppSettings["DAL"];//獲取App.Config中DAL
string _conn = "";
switch (_dal)
{
/*Sqlite數(shù)據(jù)庫(kù)*/
case "CuteMobileSearch.SQLiteDAL":
default:
_appPath = "Data Source=" + _appPath;
_appPath += System.Configuration.ConfigurationManager.AppSettings["SqliteFile"];
return _appPath;
/*SqlServer數(shù)據(jù)庫(kù)*/
case "CuteMobileSearch.SQLServerDAL":
_conn = "server=.;database=CuteMobileDB;uid=sa;pwd=123456";
return _conn;
/*access數(shù)據(jù)庫(kù)*/
case "CuteMobileSearch.OleDAL":
_appPath = "provider=microsoft.jet.oledb.4.0;data source=" + _appPath + System.Configuration.ConfigurationManager.AppSettings["OleFile"];
return _appPath;
}
}
}
然后是抽象工廠(chǎng)DAL通過(guò)使用反射創(chuàng)建接口對(duì)象的實(shí)例
/// <summary>
/// 創(chuàng)建抽象工廠(chǎng)
/// </summary>
public sealed class ObjectCreate
{
/*所使用程序集*/
public static readonly string asseblyDAL = System.Configuration.ConfigurationManager.AppSettings["DAL"];
/// <summary>
/// 創(chuàng)建對(duì)象(不使用緩存:B/S使用)
/// </summary>
/// <param name="AssemblyPath"></param>
/// <param name="classNamespace"></param>
/// <returns></returns>
private static object CreateObject(string AssemblyPath, string classNamespace)
{
try
{
object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
return objType;
}
catch
{
return null;
}
}
/// <summary>
/// 創(chuàng)建list接口對(duì)象
/// </summary>
/// <returns></returns>
public static CuteMobileSearch.IDAL.Ilist CreateListObj()
{
string className = asseblyDAL + ".listServices";
object obj = CreateObject(asseblyDAL, className);
return (CuteMobileSearch.IDAL.Ilist)obj;
}
}
IDAL聲明數(shù)據(jù)訪(fǎng)問(wèn)的接口方法
代碼
public interface Ilist
{
/*添加對(duì)象*/
int Add(CuteMobileSearch.Model.list objList);
/*返回所有*/
List<CuteMobileSearch.Model.list> GetAll();
/*根據(jù)號(hào)碼查詢(xún)*/
List<Model.list> GetListByNum(string num);
/*根據(jù)查詢(xún)條件*/
List<CuteMobileSearch.Model.list> GetListByWhere(string strWhere);
}
SqliteDAL繼承IDAL,實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)和操作,來(lái)訪(fǎng)問(wèn)實(shí)體類(lèi)Model
代碼/// <summary>
/// 基于Sqlite的數(shù)據(jù)訪(fǎng)問(wèn)類(lèi)庫(kù)
/// </summary>
public class listServices : IDAL.Ilist
{
/// <summary>
/// 添加
/// </summary>
/// <returns>返回添加數(shù)目</returns>
public int Add(CuteMobileSearch.Model.list objList)
{
StringBuilder sbSql = new StringBuilder();
sbSql.Append("INSERT INTO list(");
sbSql.Append("num,code,city,cardtype)");
sbSql.Append(" VALUES(");
sbSql.Append("@num,@code,@city,@cardtype)");
sbSql.Append(";SELECT @@IDENTITY");
SQLiteParameter[] paras ={
new SQLiteParameter("@num",DbType.String,8),
new SQLiteParameter("@code",DbType.String,8),
new SQLiteParameter("@city",DbType.String,16),
new SQLiteParameter("@cardtype",DbType.String,16)
};
paras[0].Value = objList.Num;
paras[1].Value = objList.Code;
paras[2].Value = objList.City;
paras[3].Value = objList.Cardtype;
int num = Wang.DBUtility.SqliteHelper.ExecuteCommand(sbSql.ToString());
return num;
}
/// <summary>
/// 返回List<>
/// </summary>
/// <returns></returns>
public List<CuteMobileSearch.Model.list> GetAll()
{
return GetListByWhere("");
}
/// <summary>
/// 根據(jù)號(hào)碼查詢(xún)
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public List<Model.list> GetListByNum(string num)
{
string strWhere = "num LIKE '" + num + "%'";
return GetListByWhere(strWhere);
}
/// <summary>
/// 根據(jù)條件返回List<>
/// </summary>
/// <param name="strWhere"></param>
/// <returns></returns>
public List<CuteMobileSearch.Model.list> GetListByWhere(string strWhere)
{
List<CuteMobileSearch.Model.list> listList = new List<CuteMobileSearch.Model.list>();
StringBuilder strSql = new StringBuilder();
strSql.Append("SELECT * FROM list");
if (strWhere != "")
{
strSql.Append(" WHERE ");
strSql.Append(strWhere);
}
SQLiteDataReader reader = Wang.DBUtility.SqliteHelper.GetReader(strSql.ToString());
while (reader.Read())
{
CuteMobileSearch.Model.list objList = new CuteMobileSearch.Model.list();
if (reader["id"].ToString() != String.Empty)
{
objList.Id = int.Parse(reader["id"].ToString());
}
objList.Num = reader["num"].ToString();
objList.Code = reader["code"].ToString();
objList.City = reader["city"].ToString();
objList.Cardtype = reader["cardtype"].ToString();
listList.Add(objList);
}
reader.Close();
return listList;
}
}
以其中的查詢(xún)結(jié)果的GetListByNum方法的UML類(lèi)圖如下
運(yùn)行結(jié)果
主程序運(yùn)行效果如下圖
查看詳細(xì)信息
總結(jié)
此類(lèi)基于多數(shù)據(jù)庫(kù)操作的應(yīng)用程序是很常見(jiàn)的,通過(guò)使用工廠(chǎng)方法模式進(jìn)行架構(gòu),以業(yè)務(wù)邏輯分層、抽象實(shí)現(xiàn)數(shù)據(jù)訪(fǎng)問(wèn)的思想進(jìn)行開(kāi)發(fā),顯然在程序的可擴(kuò)展性、層次性具有較大的優(yōu)勢(shì)。
另一點(diǎn)值得說(shuō)的是,Sqlite數(shù)據(jù)庫(kù)的確在一些應(yīng)用場(chǎng)合中具有較大的優(yōu)勢(shì),關(guān)于Sqlite數(shù)據(jù)庫(kù)的介紹請(qǐng)參見(jiàn)此文http://zh.wikipedia.org/wiki/SQLite
廢話(huà)
我知道這篇文章技術(shù)一般,顯然達(dá)不到cnblogs的技術(shù)層次;我本人的技術(shù)水平在cnblogs牛人面前也只是小菜鳥(niǎo)而已,發(fā)到首頁(yè)是希望大家多多拍磚,多提寶貴意見(jiàn),:)