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

  • 简单工厂模式(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. javascript(js)创建对象的模式与继承的几种方式

    1.js创建对象的几种方式 工厂模式 为什么会产生工厂模式,原因是使用同一个接口创建很多对象,会产生大量的重复代码,为了解决这个问题,产生了工厂模式. function createPerson(na ...

  2. python中html解析-Beautiful Soup

    1. Beautiful Soup的简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: Beautiful Soup提供一些简单的.pyt ...

  3. Python系列之多线程、多进程

    线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程. Python的标准库提供 ...

  4. jsp 四大域范围

     JSP中四种作用域的不同 作用域规定的是变量的有效期限. 1.如果把变量放到pageContext里,就说明它的作用域是page,它的有效范围只在当前jsp页面里. 从把变量放到pageCont ...

  5. JS实现数组每次只显示5条数据

    var array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]; //循环样式结构function fun(arr,index){ var str = &qu ...

  6. 从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD

    第1部分:http://www.cnblogs.com/cgzl/p/7637250.html 第2部分:http://www.cnblogs.com/cgzl/p/7640077.html 第3部分 ...

  7. JavaScript--我发现,原来你是这样的JS(四)(看看变量,作用域,垃圾回收机制是啥)

    一.介绍 这是红宝书(JavaScript高级程序设计 3版)的读书笔记第四篇,是红宝书第四章内容(主要是变量和作用域问题),当然其中还有我个人的理解.红宝书这本书可以说是难啃的,要看完不容易,挺厚的 ...

  8. Sqoop1.99.7将MySQL数据导入到HDFS中

    准备 本示例将实现从MySQL数据库中将数据导入到HDFS中 参考文档: http://sqoop.apache.org/docs/1.99.7/user/Sqoop5MinutesDemo.html ...

  9. 不使用数据结构反转栈 递归 CVTE实习 CVTE是一家什么公司

    本文因为垃圾csdn标题字限制,标题写不好.本文想说一个算法,和我在CVTE的实习,我看到CVTE是一家什么公司.如果想要喷我的,可以留言,我不会理.如果想喷公司,可以在博客评论或发到我邮件linde ...

  10. Java IO(IO流)-1

    IO流 第一部分 (outputStream/InputStream Writer/Redaer) IO流对象中输入和输出是相辅相成的,输出什么,就可以输入什么. IO的命名方式为前半部分能干什么,后 ...