先讲一下简单工厂模式、工厂方法模式、抽象工厂模式的东西:
- 简单工厂模式(Simple Factory Pattern):工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关类,也就是说产品的创建逻辑集中于一个工厂类,客户端只需要传递不同的参数给工厂,这时情况是:一个工厂创建一个产品,所有的具体工厂继承自一个抽象工厂;对于客户端来说,不存在与具体产品的依赖;
- 工厂方法模式(Factory Method Pattern):提前定义用于创建对象的接口,让子类决定实例化具体的某一个类,即在工厂和产品中间增加接口,工厂不再负责产品的创建,由接口针对不同条件返回具体的类实例,由具体类实例去实现;
- 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系统或相互依赖对象的接口,不需要指定具体类。抽象工厂正如其名字所说,它抽象的是工厂接口,因此它面向的是多个平等等级结构,其建立对象的原则是以功能相似的对象为单位划分需要建立的对象。
简单工厂并不属于23种基本设计模式中,它是抽象工厂模式的一个特例;抽象工厂与工厂方法区别在于它们抽象的对象不同:工厂方法针对产品进行抽象,而抽象工厂抽象针对工厂。因此可以认为工厂方法是抽象工厂的一种极端情况,工厂方法模式用来创建一个产品的等级结构,它一般只有一个方法,创建一种产品;而抽象工厂是用来创建多个产品的等级结构,一般有多个方法,创建一系列产品。
手机号码查询设计
此程序主要功能就是根据手机号码段查询相应的号码归属地。数据来自网络,数据表结构如下
数据记录超过17万条
这里我使用了Sqlite数据库,将此数据库文件转换为Sqlite数据库文件。
主程序界面设计如下:
业务逻辑分析
主程序调用业务逻辑层BLL,BLL使用抽象工厂DALFactory方法,DALFactory创建DAO实例对象,接口层IDAL定义数据操作接口方法,由数据访问层通过各自的公用数据操作类库进行读写数据库,实现对实体类Model的访问。
解决方案文件列表如图
其中DBUtility为公共数据访问类库。三个数据访问层SQLServerDAL、SqliteDAL和OleDAL分别对应Sql Server、Sqlite、Access数据库。这里我正在使用的是SqliteDAL。
具体实现
建立实体类进行对象封装
App.config定义选用的DAL及数据库连接信息
代码 public class list{ private int id; /// <summary> /// 编号 /// </summary> public int Id{ get { return id; } set { id = value; }} private string num; /// <summary> /// 号码段(手机号前7位) /// </summary> public string Num{ get { return num; } set { num = value; }} private string code; /// <summary> /// 邮政编码 /// </summary> public string Code{ get { return code; } set { code = value; }} private string city; /// <summary> /// 城市 /// </summary> public string City{ get { return city; } set { city = value; }} private string cardtype; /// <summary> /// 卡类型 /// </summary> public string Cardtype{ get { return cardtype; } set { cardtype = value; }}}
代码 <? 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"/> --> <!-- 当前使用DAL;可选以上三者之一,分别对应Sql Server、Sqlite、Access数据库 --> < 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文件用于获得相应的连接字符串ConnectionString
///<summary>/// 获得连接字符串ConnectingString///</summary>publicstaticclass SqlConnString{ publicstaticstring ReturnConnString() { string _appPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//当前程序路径 string _dal = System.Configuration.ConfigurationManager.AppSettings["DAL"];//获取App.Config中DAL string _conn =""; switch (_dal) { /*Sqlite数据库*/ case"CuteMobileSearch.SQLiteDAL": default: _appPath ="Data Source="+ _appPath; _appPath += System.Configuration.ConfigurationManager.AppSettings["SqliteFile"]; return _appPath; /*SqlServer数据库*/ case"CuteMobileSearch.SQLServerDAL": _conn ="server=.;database=CuteMobileDB;uid=sa;pwd=123456"; return _conn; /*access数据库*/ case"CuteMobileSearch.OleDAL": _appPath ="provider=microsoft.jet.oledb.4.0;data source="+ _appPath + System.Configuration.ConfigurationManager.AppSettings["OleFile"]; return _appPath; } }}
然后是抽象工厂DAL通过使用反射创建接口对象的实例
代码 /// <summary> /// 创建抽象工厂 /// </summary> public sealed class ObjectCreate{ /* 所使用程序集 */ public static readonly string asseblyDAL = System.Configuration.ConfigurationManager.AppSettings[ " DAL " ]; /// <summary> /// 创建对象(不使用缓存: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> /// 创建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声明数据访问的接口方法
代码 public interface Ilist{ /* 添加对象 */ int Add(CuteMobileSearch.Model.list objList); /* 返回所有 */ List < CuteMobileSearch.Model.list > GetAll(); /* 根据号码查询 */ List < Model.list > GetListByNum( string num); /* 根据查询条件 */ List < CuteMobileSearch.Model.list > GetListByWhere( string strWhere);} SqliteDAL继承IDAL,实现对数据库的访问和操作,来访问实体类Model
代码 /// <summary> /// 基于Sqlite的数据访问类库 /// </summary> public class listServices : IDAL.Ilist{ /// <summary> /// 添加 /// </summary> /// <returns> 返回添加数目 </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> /// 根据号码查询 /// </summary> /// <param name="num"></param> /// <returns></returns> public List < Model.list > GetListByNum( string num){ string strWhere = " num LIKE ' " + num + " %' " ; return GetListByWhere(strWhere);} /// <summary> /// 根据条件返回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;}} 以其中的查询结果的GetListByNum方法的UML类图如下
运行结果
主程序运行效果如下图
查看详细信息
总结
此类基于多数据库操作的应用程序是很常见的,通过使用工厂方法模式进行架构,以业务逻辑分层、抽象实现数据访问的思想进行开发,显然在程序的可扩展性、层次性具有较大的优势。
另一点值得说的是,Sqlite数据库的确在一些应用场合中具有较大的优势,关于Sqlite数据库的介绍请参见此文http://zh.wikipedia.org/wiki/SQLite
废话
我知道这篇文章技术一般,显然达不到cnblogs的技术层次;我本人的技术水平在cnblogs牛人面前也只是小菜鸟而已,发到首页是希望大家多多拍砖,多提宝贵意见,:)
编译后程序下载(只含Sqlite数据库):点击下载
源码下载地址(含SqlServer及Sqlite数据库):点击下载
单独Access数据库下载:点击下载