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

  • 简单工厂模式(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及数据库连接信息

代码

publicclass list
{
privateint id;
///<summary>
/// 编号
///</summary>
publicint Id
{
get { return id; }
set { id = value; }
}
privatestring num;
///<summary>
/// 号码段(手机号前7位)
///</summary>
publicstring Num
{
get { return num; }
set { num = value; }
}
privatestring code;
///<summary>
/// 邮政编码
///</summary>
publicstring Code
{
get { return code; }
set { code = value; }
}
privatestring city;
///<summary>
/// 城市
///</summary>
publicstring City
{
get { return city; }
set { city = value; }
}
privatestring cardtype;
///<summary>
/// 卡类型
///</summary>
publicstring 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>
publicsealedclass ObjectCreate
{
/*所使用程序集*/
publicstaticreadonlystring asseblyDAL = System.Configuration.ConfigurationManager.AppSettings["DAL"];

///<summary>
/// 创建对象(不使用缓存:B/S使用)
///</summary>
///<param name="AssemblyPath"></param>
///<param name="classNamespace"></param>
///<returns></returns>
privatestaticobject CreateObject(string AssemblyPath, string classNamespace)
{
try
{
object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
return objType;
}
catch
{
returnnull;
}
}

///<summary>
/// 创建list接口对象
///</summary>
///<returns></returns>
publicstatic CuteMobileSearch.IDAL.Ilist CreateListObj()
{
string className = asseblyDAL +".listServices";
object obj = CreateObject(asseblyDAL, className);
return (CuteMobileSearch.IDAL.Ilist)obj;
}
}

IDAL声明数据访问的接口方法

代码

publicinterface 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

代码

].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数据库下载:点击下载

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

  1. 极限挑战—C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码)

    原文:极限挑战-C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码) 实际工作中有时候需要把大量数据导入数据库,然后用于各种程序计算,本实验将使用5中方法完成这个过程,并详细记录各种方 ...

  2. C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码)

    作者: Aicken(李鸣)  来源: 博客园  发布时间: 2010-09-08 15:00  阅读: 4520 次  推荐: 0                   原文链接   [收藏] 摘要: ...

  3. [WinForm]FastColoredTextBox控件(附源码)

    Fast Colored TextBox is text editor component for .NET. Allows you to create custom text editor with ...

  4. 工厂方法模式——创建型模式02

    1. 简单工厂模式     在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...

  5. PHP设计模式(二)工厂方法模式(Factory Method For PHP)

    简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...

  6. Java设计模式 之 工厂方法模式

    1. 使用设计模式的好处:可提高代码的重复性,让代码更容易被他人理解,保证代码的可靠性. 2. 工厂模式定义:就是创建一个工厂类来创建你需要的类,工厂模式包括工厂模式和抽象工厂模式,抽象工厂模式是工厂 ...

  7. 深入浅出设计模式——工厂方法模式(Factory Method)

    介绍在简单工厂模式中,我们提到,工厂方法模式是简单工厂模式的一个延伸,它属于Gof23中设计模式的创建型设计模式.它解决的仍然是软件设计中与创建对象有关的问题.它可以更好的处理客户的需求变化. 引入我 ...

  8. JAVA设计模式之工厂方法模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述工厂方法模式的: 工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymor ...

  9. 六个创建模式之工厂方法模式(Factory Method Pattern)

    问题: 在使用简单工厂模式的时候,如果添加新的产品类,则必需修改工厂类,违反了开闭原则. 定义: 定义一个用于创建对象的接口,让子类决定具体实例化哪个产品类.此时工厂和产品都具有相同的继承结构,抽象产 ...

随机推荐

  1. 关于AVALON总线动态地址对齐

    在NIOS的使用中,我们往往要用到自定义外设,然后通过AVALON交换架构和NIOSII进行通信. AVALON总线,其实是一种交换架构的协议,在自定义外设挂在AVALON总线上时,一定要注意地址对齐 ...

  2. 基于nodejs+webSocket的聊天室(实现:加入聊天室、退出聊天室、在线人数、在线列表、发送信息、接收信息)

    1  安装 socket.io模块 npm install "socket.io": "latest" 2 app.js相关 ws = require('soc ...

  3. PE格式第四讲,数据目录表之导入表,以及IAT表

    PE格式第四讲,数据目录表之导入表,以及IAT表 一丶IAT(地址表) 首先我们思考一个问题,程序加载的时候会调用API,比如我们以前写的标准PE 那么他到底是怎么去调用的? 他会Call 下边的Jm ...

  4. webpack 的使用2

    实际项目中的配置 要加__dirname 不然会报错 注意path  /dist 前不要加点 结果 将两个文件打包在一起 结果 传入对象 并且单独打包 name为key 加上本次打包的hash has ...

  5. scala 读取文件遇到encode问题(Mac -> remote Linux)

    Source.fromFile(fileName)(enc: Encode),如果遇到错误: java.nio.charset.MalformedInputException: Input lengt ...

  6. elasticsearch单例模式连接

    import java.net.InetAddress;import org.elasticsearch.client.transport.TransportClient;import org.ela ...

  7. zeroc

    ZeroC ICE 是指ZeroC公司的ICE(Internet Communications Engine)中间件平台.对于客户端和服务端程序的开发提供了很大的便利. 目前ICE平台中包括Ice,I ...

  8. Hyper-v 虚拟机安装win7

    Hyper-v 是微软自带的虚拟机 一般安装win10都有 对小娜说:Hyper就会出现 进入Hyper-v 如果虚拟机不可用 启动服务 新建虚拟机 一般设置可以自己随意 虚拟机第一代才可以使用win ...

  9. JAVA判断文件的内容类型

    Java 7 新的特性,判断文件的内容类型. Program to demonstrate Java 7 new feature : Determining the file content type ...

  10. JS难点--面向对象(继承)

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Consolas; color: #a5b2b9 } 继承 让一个对象拥有另一个对象的属性或者 ...