比较好的三层的理解(转载)---基于工厂模式

在项目开发时,有时候可能会增加或修改新的数据库,比如,刚开始我们项目用SQL Server 数据库,但后来需要用Oracle 数据库,或者说在某些情况下需要用Oracle 来代替SQL Server 数据库,甚至两种情况会同时存在,但数据库访问方面 Oracle 和SQL Server 是不同的,它们的语句写法不同,甚至所示哟哦那个的.NET Framework  数据提供程序也是不同的,那应该怎么办呢?

1. 新增数据访问层

我们不修改原来的DAL的代码,可以将原来的项目命名为SQLServerDAL,我们可以增加一个针对Oracle的DAL项目来单独实现对Oracle的访问。这样就会有两个DAL,一个用于访问SQLServer,一个用于访问Oracle。

2. 实现IDAL抽象接口

由于SQL Server 和 Oracle 对数据库的基本操作是一样的,都是增、删、改、查。所以,可以将相同的功能的操作的一系列对象抽象出来实现同一个接口:IDAL。让SQLServerDAL  的类 和OracleDAL 的类都继承这个接口。具体方法如下:

(1)添加IDAL类库项目和接口文件IManager.cs,具体代码如下(由于接口中调用Model, 所以需要添加对Model项目的引用)

//IManager.cs

namespace IDAL
{
   /// <summary>
   /// 接口层IManager的摘要说明
   /// </summary>
    public interface IManager
    {
        //<summary>
        //增加一条数据
        //</summary>
        int Add(Model.Manager model);  
        //<summary>
        //更新一条数据
        //</summary>
        void Update(Model.Manager model);
        //<summary>
        //删除一条数据
        //</summary>
        void Delete(string managerid);
        //<summary>
        //得到一个实体
        //</summary>
        Hui.Model.Manager GetModel(string managerid);
        //<summary>
        //获得数据列表
        //</summary>
        DataSet GetList(string managerid);
    }

(2)在SQLServerDAL 和 OracleDAL 项目中添加对IDAL项目的引用,然后,SQLServerDAL 和 OracleDAL 项目中分别创建一个数据访问类:Manager,并继承自IManager的接口。

//SQLServerDAL.cs

using System.Data;
using System.Data.SqlClient;
using DBUtility;
using IDAL;
namespace SQLServerDAL
{
    /// <summary>
    /// Manager 数据访问类
    /// </summary>
    public class Manager:IManager
    {
        public Manager()
        { 
        }
        //<summary>
        //增加一条记录
        //</summary>
        public int Add(Model.Manager manager)
        {
            return 0;
        }
        //<summary>
        //更新一条记录
        //</summary>
        public void Update(Model.Manager manager)
        { 
        }
        //<summary>
        //删除一条记录
        //</summary>
        public void Delete(string managerid)
        { 
        }
        //<summary>
        //获得列表
        //<summary>
        public DataSet GetList(string manageid)
        {
            DataSet ds = new DataSet();
            ds = null;
            return ds;
        }
        ///<summary>
        ///得到一个对象实体
        ///</summary>
        public Model.Manager GetModel(string ManagerId)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("select ID, ManagerId, PassWord");
            strSql.Append(" from M_Manager");
            strSql.Append(" where ManagerId = @ManagerId");

SqlParameter[] parameters = {
                 new SqlParameter ("@ManagerId", SqlDbType.VarChar, 20) };
            parameters[0].Value = ManagerId;
            Model.Manager model = new Model.Manager();
            DataSet ds = DBUtility.DbHelperSQL.Query(strSql.ToString(), parameters);

if (ds.Tables[0].Rows.Count > 0)
            {
                if (ds.Tables[0].Rows[0]["ID"].ToString() != "")
                {
                    model.ID = int.Parse(ds.Tables[0].Rows[0]["ID"].ToString());
                }
                model.ManagerId = ds.Tables[0].Rows[0]["ManagerId"].ToString();
                model.PassWord = ds.Tables[0].Rows[0]["PassWord"].ToString();
              
                return model;
            }
            else
            {
                return null;
            }
        }
    }
}

//OracleDAL.cs

using System.Data;

using System.Data.OracleClient;
using IDAL;
using DBUtility;
namespace OracleDAL
{
        //<summary>
        //数据访问类
        //</summary>
        public class Manager : IManager
        {
            public Manager()
            { 
            }
            //<summary>
            //添加一条记录
            //</summary>
            public int Add(Model.Manager model)
            {
                return 0;
            }
            //<summary>
            //更新一条记录
            //</summary>
            public void Update(Model.Manager model)
            { 
            }
            //<summary>
            //获得一个实体
            //</summary>
            public Model.Manager GetModel(string managerid)
            {
                return null;
            }
            //<summary>
            //删除一条记录
            //</summary>
            public void Delete(string managerid)
            {
            }
            //<summary>
            //获得列表
            //<summary>
            public DataSet GetList(string manageid)
            {
                DataSet ds = new DataSet();
                ds = null;
                return ds;
            }
        }
    }

注:在接口里定义的所有接口方法,在派生类里必须全部实现。

3. 实现抽象工厂模式

我们需要对代码进行进一步的重构和抽象,我们可以考虑用设计模式、条件外置以及反射来实现,具体方法如下:

(1)新建DALFactory类库项目,作为创建DAL对象的工厂,并新建DataAccess类放到这个抽象工厂里面去。并添加对IDAL项目的引用。

在DataAccess类中,我们创建对象通过配置文件和反射技术实现。通过配置文件的程序集名,决定加载具体的哪个DAL的程序集,动态组合类名来动态创建DAL对象,并返回IDAL接口对象,为了性能和使用方便,DataAccess类全部采用静态方法实现。

//DataAccess.cs

using IDAL;
using System.Reflection;
using System.Configuration;
namespace DALFactory
{
    //<summary>
    //在抽象工厂中创建DAL对象
    //</summary>
    public sealed class DataAccess
    {
        private static readonly string AssemblyPath = ConfigurationManager.AppSettings["DAL"];
        //<summary>
        //创建数据层接口
        //</summary>
        public static IDAL.IManager CreateManager()
        {
            string classNamespace = AssemblyPath + ".Manager";  //类名称
            object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);  // 反射
            return (Hui.IDAL.IManager)objType;  //类型转换
        }
}

(2)实现条件外置,即通过配置文件来实现对数据访问层的判断。我们可以把需要使用的DAL类型信息放在配置文件中,然后根据配置文件来选择创建具体的对象(DAL)。

在Web.config配置文件中增加当前数据访问层的信息:

<appSettings>
    <add key="DAL" value="SQLServerDAL"/>
  </appSettings>

此外,由于反射是一种非常耗费性能的操作。所以,我们可以通过缓存的方式来进行处理。DataAccess代码改为如下:

//DadaAccess.cs

//使用缓存
        private static object CreateObject(string AssemblyPath, string classNamespace)
        {
            object objType = DataCache.GetCache(classNamespace);  //从缓存获取对象
            if (objType == null)  //缓存中没有
            {
                try
                {
                    //创建
                    objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
                    DataCache.SetCache(classNamespace, objType); // 写入缓存
                }
                catch
                { 
                }
            }
            return objType;
        }
        //<summary>
        //创建数据访问层
        //</summary>
        public static IDAL.IManager CreateManager()
        {
            string classNamespace = AssemblyPath + ".Manager";
            object objType = CreateObject(AssemblyPath, classNamespace);
            return (IDAL.IManager)objType;
        }

(3)为BLL项目添加对IDAL 和 DALFactory项目的引用。在BLL层中通过DALFactory 来创建DAL对象的接口调用,而不用关心具体该调用哪个DAL对象。BLL代码如下:

//BLLManager.cs

namespace BLL
{
    /// <summary>
    /// 业务逻辑类Manager
    /// </summary>
    public class Manager
    {

//从工厂里面创建数据访问类
        IDAL.IManager dal = .DALFactory.DataAccess.CreateManager();
        public Manager()
        { 
        }
        ///<summary>
        ///查询一条数据
        ///</summary>
        public Model.Manager GetModel(string ManagerId)
        {
            return dal.GetModel(ManagerId);
        }
       //其他代码省略。。。。。。。。。。
    }
}

时间: 2024-08-21 14:39:36

比较好的三层的理解(转载)---基于工厂模式的相关文章

设计模式粗浅理解之一------简单工厂模式

设计模式粗浅理解之------简单工厂模式 什么是简单工厂模式 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现. 角色和职责 工厂(Creator)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑.工厂类可以被外界直接调用,创建所需的产

升级版:由简单三层,升级到简单工厂模式

前面,复习了简单三层.可以看出三层的缺点,业务层和数据访问层耦合在一起了,如果后面我需要在上面扩展的话,就不方便了,比如,现在我只是支持微软的SQL Server数据库,要是我后面想支持MySQL,Oracle数据库呢...?这该咋办?你可以说,这好办,重新把访问数据库的类和方法写一遍..显然这不是好方法.不符合,软件设计的封装性--封装变化点原则. 下面看下业务层的代码吧: using DAL; using Entity; using IDAL; using System; using Sys

自己理解的java工厂模式,希望对大家有所帮助

[http://www.360doc.com/content/11/0824/17/3034429_142983837.shtml] 这两天突然想学学java源代码,不过看到一篇文章说看java源代码要先看设计模式,这样更容易理解源代码的结构,所以就准备学学java设计模式,首先当然是看java创建模式的工厂模式了,刚开始直接看抽象工厂模式是什么意思,百度百科的实在是看不懂,后来又在网上看了看其他的文章,仔细思考后,还算是理解了,现在跟大家分享下. 首先说说简单工厂模式,我用现实中的汽车工厂举例

5分钟理解设计模式之工厂模式

工厂模式是Java中最常用的设计模式.工厂模式提供很好的创建对象的方式,属于创建型模式. 使用工厂模式创建对象是不向使用者暴露创建细节,并且可以通过统一的接口引用对象. 实现 我们将创建Shape接口和实现Shape接口的具体类.下一步再声明工厂类ShapeFactory. 示例类FactoryPatternDemo使用ShapeFactory获取Shape对象.通过给ShapeFactory传递图形参数(CIRCLE / RECTANGLE / SQUARE)来获取需要的对象. 第1步 创建一

理解Spring、工厂模式和原始方法的说明

[email&#160;protected]_LabVIEW工厂模式理解

前言 折腾了一天,基本上搞清楚了简单工厂.工厂模式 理解 无论是简单工厂还是工厂模式,都有一个特点,即工厂加工的方式是不变的,产品的类型可以不断扩展:如果加工方式也会变化,修改工厂模式的加工方式会导致工厂原有的一些内容发生改变,此时要使用策略模式,利用组合实现更多的可配置: 简单工厂模式 简单工厂模式UML 理解 简单工厂模式实际上是将初始化实例的内容放在了一个工厂类里面,通过一个参数,实现类的实例化,适用于只知道传入了工厂类的参数,对于始何创建对象(逻辑)不关心时候.由于将初始化实例放在了一个

深入理解工厂模式

Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_Guide 历史回顾: 深入理解单例模式 历史文章推荐: 分布式系统的经典基础理论 可能是最漂亮的Spring事务管理详解 面试中关于Java虚拟机(jvm)的问题看这篇就够了 [TOC] 一 工厂模式介绍 1.1 工厂模式的定义 先来看一下GOF为工厂模式的定义: "Define an interface for creating an

深刻理解JavaScript基于原型的面向对象

主题一.原型 一.基于原型的语言的特点 1 只有对象,没有类;对象继承对象,而不是类继承类. 2  "原型对象"是基于原型语言的核心概念.原型对象是新对象的模板,它将自身的属性共享给新对象.一个对象不但可以享有自己创建时和运行时定义的属性,而且可以享有原型对象的属性. 3 除了语言原生的顶级对象,每一个对象都有自己的原型对象,所有对象构成一个树状的层级系统.root节点的顶层对象是一个语言原生的对象,其他所有对象都直接或间接继承它的属性. 显然,基于原型的语言比基于类的语言简单得多,我

C#中Thread类中Join方法的理解(转载)

指在一线程里面调用另一线程join方法时,表示将本线程阻塞直至另一线程终止时再执行      比如 Java代码   using System; namespace TestThreadJoin { class Program { static void Main() { System.Threading.Thread x = new System.Threading.Thread(new System.Threading.ThreadStart(f1)); x.Start(); Console