三层架构学习----PetShop跟彬月论坛对比

彬月论坛

UI层:

(new FavoriteService()).Append(this.TopicID, Visitor.Current.NickName);

业务逻辑层

  public void Append(int topicID, string nickName)
  {
   if (topicID <= 0 || nickName == null || nickName == "")
    return;

   this.DriveFavoriteTask().Append(topicID, nickName);
  }

  /// <summary>
  /// 驱动收藏夹数据库任务
  /// </summary>
  /// <returns></returns>
  private IFavoriteTask DriveFavoriteTask()
  {
   return DBTaskDriverBase.Instance.DriveFavoriteTask();
  }

数据访问层接口定义:

void Append(int topicID, string nickName);

SQLServer数据访问层:

  public void Append(int topicID, string nickName)
  {
   if (topicID <= 0 || nickName == null || nickName == "")
    return;

   MySqlParamCollection parameters = new MySqlParamCollection();

   // 设置主题编号
   parameters.Add("@TopicID", SqlDbType.Int).Value = topicID;
   // 设置用户名称
   parameters.Add("@NickName", SqlDbType.NVarChar, 20).Value = nickName;

   // 执行 SQL 查询
   SQLHelper.ExecuteNoneQuery(SQL_APPEND, CommandType.StoredProcedure, parameters.ToArray());
  }

数据层的抽象工厂:

  /// <summary>
  /// 获取数据库任务驱动实例
  /// </summary>
  /// <returns></returns>
  public static DBTaskDriverBase Instance
  {
   get
   {
    if (g_theInstance != null)
     return g_theInstance;

    lock (typeof(DBTaskDriverBase))
    {
     if (g_theInstance == null)
     {
      Type type = Type.GetType(SystemConfManager.Context.DALConf.ActiveProvider.DBTaskDriver);

      // 建立 DBTaskDriverBase 数据库任务驱动实例
      DBTaskDriverBase instance = Activator.CreateInstance(type) as DBTaskDriverBase;

      g_theInstance = instance;
     }
    }

    // 返回数据库任务驱动实例
    return g_theInstance;
   }
  }

public abstract IFavoriteTask DriveFavoriteTask();

这其中还有掌管接口实例的DBTaskDriver

public override IFavoriteTask DriveFavoriteTask()
  {
   return new FavoriteTask();
  }

我们在看一下PetShop的代码

UI层:

            //get category id
            string categoryKey = Request.QueryString["categoryId"];

            //bind data
            Product product = new Product();
            productsList.DataSource = product.GetProductsByCategory(categoryKey);
            productsList.DataBind();

业务逻辑层

private static readonly IProduct dal = PetShop.DALFactory.DataAccess.CreateProduct();

  public IList<ProductInfo> GetProductsByCategory(string category) {

   // Return new if the string is empty
   if(string.IsNullOrEmpty(category))
    return new List<ProductInfo>();

   // Run a search against the data store
   return dal.GetProductsByCategory(category);
  }

数据访问层接口定义:

IList<ProductInfo> GetProductsByCategory(string category); 

SQLServer数据访问层:

        public IList<ProductInfo> GetProductsByCategory(string category) {

            IList<ProductInfo> productsByCategory = new List<ProductInfo>();

            SqlParameter parm = new SqlParameter(PARM_CATEGORY, SqlDbType.VarChar, 10);
            parm.Value = category;

            //Execute a query to read the products
            using (SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_Select_PRODUCTS_BY_CATEGORY, parm)) {
                while (rdr.Read()) {
                    ProductInfo product = new ProductInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2), rdr.GetString(3), rdr.GetString(4));
                    productsByCategory.Add(product);
                }
            }

            return productsByCategory;
        }

数据层的抽象工厂:

private static readonly string path = ConfigurationManager.AppSettings["WebDAL"];

        public static PetShop.IDAL.IProduct CreateProduct() {
            string className = path + ".Product";
            return (PetShop.IDAL.IProduct)Assembly.Load(path).CreateInstance(className);
        }

我们分析一下,二者实现上的区别:

   PetShop在业务逻辑层中,使用了一个单利,为了不重复建立具体的数据访问层对象,然后,在中间层是调用数据访问层的同名函数,其跟冰月论坛在SQLServer数据访问层上基本相同!只是在数据层的抽象工厂有一些差别!

   在彬月论坛中,业务逻辑层使用return DBTaskDriverBase.Instance.DriveFavoriteTask(),DriveXXXTask() 来建立一个具体的接口实例,而 PetShop 则是使用不同的工厂方法,来建立不同的接口实例!使用PetShop这种方式会在配置文件里写比较多的配置信息。而彬月论坛只写一个配置信息,就可以产生不同的接口实例,不是直接产生某个接口的实例,而是先产生一个被我称之为 DBTaskDriver 的东西,你可以把它视作掌管接口实例的大总管。要想建立接口实例,先得建立这个大总管,然后再由它来建立具体的接口实例。虽然大总管具备建立具体接口的能力,但是他并不能知道到底真的要建立具体哪个实例?所以,只好将他这种能力抽象化,他变成了一个抽象的大总管,而且建立具体接口的能力被推迟到了具体的数据访问层里。这样,我只需要知道:1. 我呼叫大总管, 2. 大总管告诉具体的接口实例,而不是,我呼叫工厂类里的每个具体的工厂!在抽象大总管中,覆盖数据层的抽象工厂里的抽象类!

 
在刚刚步入“多层结构”Web应用程序开发的时候,我阅读过几篇关于“asp.net三层结构开发”的文章。但其多半都是对PetShop3.0和Duwamish7的局部剖析或者是学习笔记。对“三层结构”通体分析的学术文章几乎没有。 2005年211日,Bincess BBS论坛开始试运行。不久之后,我写了一篇题目为《浅谈“三层结构”原理与用意》的文章。旧版文章以论坛程序中的部分代码举例,通过全局视角阐述了什么是“三层结构”的开发模式?为什么要这样做?怎样做?……而在这篇文章的新作中,配合这篇文章我写了7个程序实例(TraceLWord1~TraceLWord7留言板)以帮助读者理解“三层结构”应用程序。这些程序示例可以在随带的CodePackage目录中找到——   对于那些有丰富经验的Web应用程序开发人员,他们认为文章写的通俗易懂,很值得一读。可是对于asp.net初学者,特别是没有任何开发经验的人,文章阅读起来就感到非常困难,不知文章所云。甚至有些读者对“三层结构”的认识更模糊了……   关于“多层结构”开发模式,存在这样一种争议:一部分学者认为“多层结构”与“面向对象的程序设计思想”有着非常紧密的联系。而另外一部分学者却认为二者之间并无直接联系。写作这篇文章并不是要终结这种争议,其行文目的是希望读者能够明白:在使用asp.net进行Web应用程序开发时,实现“多层结构”开发模式的方法、原理及用意。要顺利的阅读这篇文章,希望读者能对“面向对象的程序设计思想”有一定深度的认识,最好能懂一些“设计模式”的知识。如果你并不了解前面这些,那么这篇文章可能并不适合你现在阅读。不过,无论这篇文章面对的读者是谁,我都会尽量将文章写好。我希望这篇文章能成为学习“三层结构”设计思想的经典文章!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值