2010年4月3日使用工廠方法模式實現(xiàn)多數(shù)據(jù)庫WinForm手機號碼查詢器(附源碼)
關(guān)于工廠模式
先講一下簡單工廠模式、工廠方法模式、抽象工廠模式的東西:
- 簡單工廠模式(Simple Factory Pattern):工廠類中包含了必要的邏輯判斷,根據(jù)客戶端的選擇條件動態(tài)實例化相關(guān)類,也就是說產(chǎn)品的創(chuàng)建邏輯集中于一個工廠類,客戶端只需要傳遞不同的參數(shù)給工廠,這時情況是:一個工廠創(chuàng)建一個產(chǎn)品,所有的具體工廠繼承自一個抽象工廠;對于客戶端來說,不存在與具體產(chǎn)品的依賴;
- 工廠方法模式(Factory Method Pattern):提前定義用于創(chuàng)建對象的接口,讓子類決定實例化具體的某一個類,即在工廠和產(chǎn)品中間增加接口,工廠不再負(fù)責(zé)產(chǎn)品的創(chuàng)建,由接口針對不同條件返回具體的類實例,由具體類實例去實現(xiàn);
- 抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系統(tǒng)或相互依賴對象的接口,不需要指定具體類。抽象工廠正如其名字所說,它抽象的是工廠接口,因此它面向的是多個平等等級結(jié)構(gòu),其建立對象的原則是以功能相似的對象為單位劃分需要建立的對象。
簡單工廠并不屬于23種基本設(shè)計模式中,它是抽象工廠模式的一個特例;抽象工廠與工廠方法區(qū)別在于它們抽象的對象不同:工廠方法針對產(chǎn)品進行抽象,而抽象工廠抽象針對工廠。因此可以認(rèn)為工廠方法是抽象工廠的一種極端情況,工廠方法模式用來創(chuàng)建一個產(chǎn)品的等級結(jié)構(gòu),它一般只有一個方法,創(chuàng)建一種產(chǎn)品;而抽象工廠是用來創(chuàng)建多個產(chǎn)品的等級結(jié)構(gòu),一般有多個方法,創(chuàng)建一系列產(chǎn)品。
手機號碼查詢設(shè)計
此程序主要功能就是根據(jù)手機號碼段查詢相應(yīng)的號碼歸屬地。數(shù)據(jù)來自網(wǎng)絡(luò),數(shù)據(jù)表結(jié)構(gòu)如下
數(shù)據(jù)記錄超過17萬條
這里我使用了Sqlite數(shù)據(jù)庫,將此數(shù)據(jù)庫文件轉(zhuǎn)換為Sqlite數(shù)據(jù)庫文件。
主程序界面設(shè)計如下:
業(yè)務(wù)邏輯分析
主程序調(diào)用業(yè)務(wù)邏輯層BLL,BLL使用抽象工廠DALFactory方法,DALFactory創(chuàng)建DAO實例對象,接口層IDAL定義數(shù)據(jù)操作接口方法,由數(shù)據(jù)訪問層通過各自的公用數(shù)據(jù)操作類庫進行讀寫數(shù)據(jù)庫,實現(xiàn)對實體類Model的訪問。
解決方案文件列表如圖
其中DBUtility為公共數(shù)據(jù)訪問類庫。三個數(shù)據(jù)訪問層SQLServerDAL、SqliteDAL和OleDAL分別對應(yīng)Sql Server、Sqlite、Access數(shù)據(jù)庫。這里我正在使用的是SqliteDAL。
具體實現(xiàn)
建立實體類進行對象封裝
App.config定義選用的DAL及數(shù)據(jù)庫連接信息
代碼
<?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;可選以上三者之一,分別對應(yīng)Sql Server、Sqlite、Access數(shù)據(jù)庫-->
<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ù)庫*/
case "CuteMobileSearch.SQLiteDAL":
default:
_appPath = "Data Source=" + _appPath;
_appPath += System.Configuration.ConfigurationManager.AppSettings["SqliteFile"];
return _appPath;
/*SqlServer數(shù)據(jù)庫*/
case "CuteMobileSearch.SQLServerDAL":
_conn = "server=.;database=CuteMobileDB;uid=sa;pwd=123456";
return _conn;
/*access數(shù)據(jù)庫*/
case "CuteMobileSearch.OleDAL":
_appPath = "provider=microsoft.jet.oledb.4.0;data source=" + _appPath + System.Configuration.ConfigurationManager.AppSettings["OleFile"];
return _appPath;
}
}
}
然后是抽象工廠DAL通過使用反射創(chuàng)建接口對象的實例
/// <summary>
/// 創(chuàng)建抽象工廠
/// </summary>
public sealed class ObjectCreate
{
/*所使用程序集*/
public static readonly string asseblyDAL = System.Configuration.ConfigurationManager.AppSettings["DAL"];
/// <summary>
/// 創(chuàng)建對象(不使用緩存: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接口對象
/// </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ù)訪問的接口方法
代碼
public interface Ilist
{
/*添加對象*/
int Add(CuteMobileSearch.Model.list objList);
/*返回所有*/
List<CuteMobileSearch.Model.list> GetAll();
/*根據(jù)號碼查詢*/
List<Model.list> GetListByNum(string num);
/*根據(jù)查詢條件*/
List<CuteMobileSearch.Model.list> GetListByWhere(string strWhere);
}
SqliteDAL繼承IDAL,實現(xiàn)對數(shù)據(jù)庫的訪問和操作,來訪問實體類Model
代碼/// <summary>
/// 基于Sqlite的數(shù)據(jù)訪問類庫
/// </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ù)號碼查詢
/// </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;
}
}
以其中的查詢結(jié)果的GetListByNum方法的UML類圖如下
運行結(jié)果
主程序運行效果如下圖
查看詳細(xì)信息
總結(jié)
此類基于多數(shù)據(jù)庫操作的應(yīng)用程序是很常見的,通過使用工廠方法模式進行架構(gòu),以業(yè)務(wù)邏輯分層、抽象實現(xiàn)數(shù)據(jù)訪問的思想進行開發(fā),顯然在程序的可擴展性、層次性具有較大的優(yōu)勢。
另一點值得說的是,Sqlite數(shù)據(jù)庫的確在一些應(yīng)用場合中具有較大的優(yōu)勢,關(guān)于Sqlite數(shù)據(jù)庫的介紹請參見此文http://zh.wikipedia.org/wiki/SQLite
廢話
我知道這篇文章技術(shù)一般,顯然達不到cnblogs的技術(shù)層次;我本人的技術(shù)水平在cnblogs牛人面前也只是小菜鳥而已,發(fā)到首頁是希望大家多多拍磚,多提寶貴意見,:)