使用工厂方法模式实现多数据库WinForm手机号码查询器(附源码)

关于工厂模式

先讲一下简单工厂模式、工厂方法模式、抽象工厂模式的东西:

  • 简单工厂模式(Simple Factory Pattern):工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关类,也就是说产品的创建逻辑集中于一个工厂类,客户端只需要传递不同的参数给工厂,这时情况是:一个工厂创建一个产品,所有的具体工厂继承自一个抽象工厂;对于客户端来说,不存在与具体产品的依赖;
  • 工厂方法模式(Factory Method Pattern):提前定义用于创建对象的接口,让子类决定实例化具体的某一个类,即在工厂和产品中间增加接口,工厂不再负责产品的创建,由接口针对不同条件返回具体的类实例,由具体类实例去实现;
  • 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系统或相互依赖对象的接口,不需要指定具体类。抽象工厂正如其名字所说,它抽象的是工厂接口,因此它面向的是多个平等等级结构,其建立对象的原则是以功能相似的对象为单位划分需要建立的对象。

简单工厂并不属于23种基本设计模式中,它是抽象工厂模式的一个特例;抽象工厂与工厂方法区别在于它们抽象的对象不同:工厂方法针对产品进行抽象,而抽象工厂抽象针对工厂。因此可以认为工厂方法是抽象工厂的一种极端情况,工厂方法模式用来创建一个产品的等级结构,它一般只有一个方法,创建一种产品;而抽象工厂是用来创建多个产品的等级结构,一般有多个方法,创建一系列产品。

手机号码查询设计

此程序主要功能就是根据手机号码段查询相应的号码归属地。数据来自网络,数据表结构如下

2010040300595069.png

数据记录超过17万条

2010040301001067.png

这里我使用了Sqlite数据库,将此数据库文件转换为Sqlite数据库文件。

主程序界面设计如下:

2010040301024620.png

业务逻辑分析

主程序调用业务逻辑层BLL,BLL使用抽象工厂DALFactory方法,DALFactory创建DAO实例对象,接口层IDAL定义数据操作接口方法,由数据访问层通过各自的公用数据操作类库进行读写数据库,实现对实体类Model的访问。

2010040301064869.png

解决方案文件列表如图

2010040301121964.png

其中DBUtility为公共数据访问类库。三个数据访问层SQLServerDAL、SqliteDAL和OleDAL分别对应Sql Server、Sqlite、Access数据库。这里我正在使用的是SqliteDAL。

具体实现

建立实体类进行对象封装

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
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; }
}
}

App.config定义选用的DAL及数据库连接信息

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
<? 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

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
/// <summary>
/// 获得连接字符串ConnectingString
/// </summary>
public static class SqlConnString
{
public static string 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通过使用反射创建接口对象的实例

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
/// <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声明数据访问的接口方法

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
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

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
/// <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;
}
}

Sqlite数据库操作公共库SqliteHelper全部代码如下

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SQLite;
/* ***************************************
* Assembly:Wang.DBUtility
* Author:walking
* E-mail:walkingp@126.com
* Homepage:
http://www.51obj.cn/
* Last Modified:2010-4-2
* Description:the common database access class libary for Sqlite,all copyright served by walkingp.
* *************************************
*/
namespace Wang.DBUtility
{
/// <summary>
/// Sqlite数据操作公共类
/// </summary>
public static class SqliteHelper
{
/// <summary>
/// 连接字符串
/// </summary>
public static string ConnStr
{
get
{
// 调试时使用
string appPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
int index = AppDomain.CurrentDomain.SetupInformation.ApplicationBase.LastIndexOf( " \\ " );
appPath
= " Data Source= " + appPath.Substring( 0 , index);
appPath
= appPath.Substring( 0 , appPath.LastIndexOf( " \\ " ));
appPath
= appPath.Substring( 0 , appPath.LastIndexOf( " \\ " ));
appPath
+= System.Configuration.ConfigurationManager.AppSettings[ " SqliteFile " ];
string _conn = appPath;
return _conn;
/* return SqlConnString.ReturnConnString(); */
}
}

private static SQLiteConnection _conn;
/// <summary>
/// SQLiteConnection
/// </summary>
public static SQLiteConnection Conn
{
get
{
SQLiteConnection conn
= new SQLiteConnection(ConnStr);
conn.Open();
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
else if (conn.State == ConnectionState.Broken)
{
conn.Close();
conn.Open();
}
return conn;
}
set { _conn = value; }
}

/// <summary>
/// 关闭连接
/// </summary>
public static void ConnClose()
{
if (Conn.State != ConnectionState.Closed)
Conn.Close();
}
/// <summary>
/// 执行SQL
/// </summary>
/// <param name="strSql"></param>
/// <returns></returns>
public static int ExecuteCommand( string strSql)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
int i = cmd.ExecuteNonQuery();
return i;
}
/// <summary>
/// 带参数的执行SQL
/// </summary>
/// <param name="strSql"></param>
/// <param name="paras"></param>
/// <returns></returns>
public static int ExecuteCommand( string strSql, params SQLiteParameter[] paras)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
cmd.Parameters.AddRange(paras);
int i = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return i;
}
/// <summary>
/// 返回一行记录
/// </summary>
/// <param name="strSql"></param>
/// <returns></returns>
public static int GetScalar( string strSql)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
int i = Convert.ToInt32(cmd.ExecuteScalar());
return i;
}
/// <summary>
/// 返回一行记录
/// </summary>
/// <param name="strSql"></param>
/// <param name="paras"></param>
/// <returns></returns>
public static int GetScalar( string strSql, params SQLiteParameter[] paras)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
cmd.Parameters.AddRange(paras);
int i = Convert.ToInt32(cmd.ExecuteScalar());
cmd.Parameters.Clear();
return i;
}
/// <summary>
/// 返回SQLiteDataReader
/// </summary>
/// <param name="strSql"></param>
/// <returns></returns>
public static SQLiteDataReader GetReader( string strSql)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
SQLiteDataReader dr
= cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
return dr;
}
/// <summary>
/// 带参数返回SQLiteDataReader
/// </summary>
/// <param name="strSql"></param>
/// <returns></returns>
public static SQLiteDataReader GetReader( string strSql, params SQLiteParameter[] paras)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
cmd.Parameters.AddRange(paras);
SQLiteDataReader dr
= cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
return dr;
}
/// <summary>
/// 返回DataTable
/// </summary>
/// <param name="strSql"></param>
/// <returns></returns>
public static DataTable GetDataTable( string strSql)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
DataSet ds
= new DataSet();
SQLiteDataAdapter da
= new SQLiteDataAdapter(cmd);
ds.Clear();
da.Fill(ds);
return ds.Tables[ 0 ];
}
/// <summary>
/// 带参数返回DataTable
/// </summary>
/// <param name="strSql"></param>
/// <returns></returns>
public static DataTable GetDataTable( string strSql, params SQLiteParameter[] paras)
{
SQLiteCommand cmd
= new SQLiteCommand(strSql, Conn);
cmd.Parameters.AddRange(paras);
SQLiteDataAdapter da
= new SQLiteDataAdapter(cmd);
DataSet ds
= new DataSet();
ds.Clear();
da.Fill(ds);
return ds.Tables[ 0 ];
}
}
}

 

以其中的查询结果的GetListByNum方法的UML类图如下

2010040301074562.jpg

运行结果

主程序运行效果如下图

2010040301325765.png

查看详细信息

2010040301333470.png

总结

此类基于多数据库操作的应用程序是很常见的,通过使用工厂方法模式进行架构,以业务逻辑分层、抽象实现数据访问的思想进行开发,显然在程序的可扩展性、层次性具有较大的优势。

另一点值得说的是,Sqlite数据库的确在一些应用场合中具有较大的优势,关于Sqlite数据库的介绍请参见此文http://zh.wikipedia.org/wiki/SQLite

废话

我知道这篇文章技术一般,显然达不到cnblogs的技术层次;我本人的技术水平在cnblogs牛人面前也只是小菜鸟而已,发到首页是希望大家多多拍砖,多提宝贵意见,:)

 

编译后程序下载(只含Sqlite数据库):http://files.cnblogs.com/walkingp/CuteMobileSearch_bin.zip

源码下载地址(含SqlServer及Sqlite数据库):http://files.cnblogs.com/walkingp/CuteMobileSearch_src.zip

单独Access数据库下载:http://files.cnblogs.com/walkingp/CuteMobileSearch_AccessDB.zip

转载于:https://www.cnblogs.com/walkingp/archive/2010/04/03/1703475.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值