zoukankan      html  css  js  c++  java
  • 收集的.Net文章(十九)浅谈"三层结构"原理与用意(2)

         从前面的程序段中可以看出,ListLWord.aspx.csPostLWord.aspx.cs这两个文件已经找不到和数据库相关的代码了。只看到一些和LWordTask类有关系的代码,这就符合了“设计模式”中的一种重要原则:“迪米特法则”。“迪米特法则”主要是说:让一个“类”与尽量少的其它的类发生关系。TraceLWord1中,ListLWord.aspx.cs这个类和OleDbConnectionOleDbDataAdapter都发生了关系,所以它破坏了“迪米特法则”。利用一个“中间人”是“迪米特法则”解决问题的办法,这也是“门面模式”必须遵循的原则。下面就引出这个LWordTask门面类的示意图:
     

    ListLWord.aspx.csPostLWord.aspx.cs两个文件对数据库的访问,全部委托LWordTask类这个“中间人”来办理。利用“门面模式”,将页面类和数据库类进行隔离。这样就作到了页面类不依赖于数据库的效果。以一段比较简单的代码来描述这三个程序的关系:

     

    public class ListLWord

    {

    private void LWord_DataBind()

    {

        (new LWordTask()).ListLWord( ... );

        }

    }

     

    public class PostLWord

    {

        private void Post_ServerClick(object sender, EventArgs e)

        {

            (new LWordTask()).PostLWord( ... );

        }

    }

     

    public class LWordTask

    {

        public DataSet ListLWord(DataSet ds)...

     

        public void PostLWord(string textContent)...

    }

     


    应用中间业务层,实现“三层结构”

    前面这种分离数据访问代码的形式,可以说是一种“三层结构”的简化形式。因为它没有“中间业务层”也可以称呼它为“二层结构”。一个真正的“三层”程序,是要有“中间业务层”的,而它的作用是连接“外观层”和“数据访问层”。换句话说:“外观层”的任务先委托给“中间业务层”来办理,然后“中间业务层”再去委托“数据访问层”来办理……

    那么为什么要应用“中间业务层”呢?“中间业务层”的用途有很多,例如:验证用户输入数据、缓存从数据库中读取的数据等等……但是,“中间业务层”的实际目的是将“数据访问层”的最基础的存储逻辑组合起来,形成一种业务规则。例如:“在一个购物网站中有这样的一个规则:在该网站第一次购物的用户,系统为其自动注册”。这样的业务逻辑放在中间层最合适:
     

    在“数据访问层”中,最好不要出现任何“业务逻辑”!也就是说,要保证“数据访问层”的中的函数功能的原子性!即最小性和不可再分。“数据访问层”只管负责存储或读取数据就可以了。

      在新TraceLWord3中,应用了“企业级模板项目”。把原来的LWordTask.cs,并放置到一个单一的项目里,项目名称为:AccessTask。解决方案中又新建了一个名称为:InterService的项目,该项目中包含一个LWordService.cs程序文件,它便是“中间业务层”程序。为了不重复命名,TraceLWord3的网站被放置到了WebUI项目中。更完整的代码,可以在CodePackage/TraceLWord3目录中找到——


     

    这些类的关系,也可以表示为如下的示意图:

     

    LWordService.cs程序源码:

     

    #001 using System;

    #002 using System.Data;

    #003

    #004 using TraceLWord3.AccessTask;      // 引用数据访问层

    #005

    #006 namespace TraceLWord3.InterService

    #007 {

    #008    /// <summary>

    #009    /// LWordService 留言板服务类

    #010    /// </summary>

    #011    public class LWordService

    #012    {

    #013        /// <summary>

    #014        /// 读取数据库表 LWord,并填充 DataSet 数据集

    #015        /// </summary>

    #016        /// <param name="ds">填充目标数据集</param>

    #017        /// <param name="tableName">表名称</param>

    #018        /// <returns>记录行数</returns>

    #019        public int ListLWord(DataSet ds, string tableName)

    #020        {

    #021            return (new LWordTask()).ListLWord(ds, tableName);

    #022        }

    #023

    #024        /// <summary>

    #025        /// 发送留言信息到数据库

    #026        /// </summary>

    #027        /// <param name="textContent">留言内容</param>

    #028        public void PostLWord(string content)

    #029        {

    #030            (new LWordTask()).PostLWord(content);

    #031        }

    #032    }

    #033 }

     

    LWordService.cs程序文件的行#021和行#030可以看出,“中间业务层”并没有实现什么业务逻辑,只是简单的调用了“数据访问层”的类方法……这样做是为了让读者更直观的看明白“三层结构”应用程序的调用顺序,看清楚它的全貌。加入了“中间业务层”,那么原来的ListLWord.aspx.cs文件应该作以修改:


     

    ...

    #012 using TraceLWord3.InterService;        // 引用中间服务层

    ...

    #045        /// <summary>

    #046        /// 绑定留言信息列表

    #047        /// </summary>

    #048        private void LWord_DataBind()

    #049        {

    #050            DataSet ds=new DataSet();

    #051            (new LWordService()).ListLWord(ds, @"LWordTable");

    #052

    #053            m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;

    #054            m_lwordListCtrl.DataBind();

    #055        }

    ...

     

    原来的PostLWord.aspx.cs文件也应作以修改:

     

    ...

    #012 using TraceLWord3.InterService;        // 引用中间服务层

    ...

    #047        /// <summary>

    #048        /// 发送留言到数据库

    #049        /// </summary>

    #050        private void Post_ServerClick(object sender, EventArgs e)

    #051        {

    #052            // 获取留言内容

    #053            string textContent=this.m_txtContent.Value;

    #054

    #055            (new LWordService()).PostLWord(textContent);

    #056

    #057            // 跳转到留言显示页面

    #058            Response.Redirect("ListLWord.aspx", true);

    #059        }

    ...

     

     


    到目前为止,TraceLWord3程序已经是一个简单的“三层结构”的应用程序,以一段比较简单的代码来描述四个程序的关系:

     

    namespace TraceLWord3.WebLWord

    {

    public class ListLWord

    {

            private void LWord_DataBind()

            {

                (new LWordService()).ListLWord( ... );

            }

    }

     

        public class PostLWord

        {

            private void Post_ServerClick(object sender, EventArgs e)

            {

                (new LWordService()).PostLWord( ... );

            }

        }

    }

     

    namespace TraceLWord3.InterService

    {

        public class LWordTask

        {

            public DataSet ListLWord(DataSet ds, string tableName)

            {

                return (new LWordTask()).ListLWord(ds, tableName);

            }

     

            public void PostLWord(string content)

            {

                (new LWordTask()).PostLWord(content);

            }

        }

    }

     

    namespace TraceLWord3.AccessTask

    {

    public class LWordTask

    {

            public DataSet ListLWord(DataSet ds)...

     

            public void PostLWord(string content)...

    }

    }


    用户在访问TraceLWord3ListLWord.aspx页面时序图:

     

    当一个用户访问TraceLWord5ListLWord.aspx页面的时候,会触发该页面后台程序中的Page_Load函数。而在该函数中调用了LWord_DataBind函数来获取留言板信息。由图中可以看到出,LWord_DataBind在被调用的期间,会建立一个新的LWordService类对象,并调用这个对象的ListLWord函数。在LWordService.ListLWord函数被调用的期间,会建立一个新的LWordTask类对象,并调用这个对象的ListLWord来获取留言板信息的。PostLWord.aspx页面时序图,和上面这个差不多。就是这样,经过一层又一层的调用,来获取返回结果或是保存数据。

     

    注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失……


    对“三层结构”的深入理解——怎样才算是一个符合“三层结构”的Web应用程序?

    在一个ASP.NET Web应用程序解决方案中,并不是说有aspx文件、有dll文件、还有数据库,就是“三层结构”的Web应用程序,这样的说法是不对的。也并不是说没有对数据库进行操作,就不是“三层结构”的。其实“三层结构”是功能实现上的三层。例如,在微软的ASP.NET示范实例“Duwamish7中,“表现层”被放置在“Web”项目中,“中间业务层”是放置在“BusinessFacade”项目中,“数据访问层”则是放置在“DataAccess”项目中……而在微软的另一个ASP.NET示范实例“PetShop3.0中,“表现层”被放置在“Web”项目中,“中间业务层”是放置在“BLL”项目中,而“数据访问层”则是放置在“SQLServerDAL”和“OracleDAL”两个项目中。Bincess.CN彬月论坛中,“表现层”是被放置在“WebForum”项目中,“中间业务(服务)层”是被放置在“InterService”项目中,而“数据访问层”是被放置在“SqlServerTask”项目中。

      如果只以分层的设计角度看,Duwamish7要比PetShop3.0复杂一些!而如果较为全面的比较二者,PetShop3.0则显得比较复杂。但我们先不讨论这些,对PetShop3.0Duwamish7的研究,并不是本文的重点。现在的问题就是:既然“三层结构”已经被分派到各自的项目中,那么剩下来的项目是做什么的呢?例如PetShop3.0中的“Model”、“IDAL”、“DALFactory”这三个项目,再例如Duwamish7中的“Common”项目,还有就是在Bincess.CN彬月论坛中的“Classes”、“DbTask”、这两个项目。它们究竟是做什么用的呢?

     

    对“三层结构”的深入理解——从一家小餐馆说起

      一个“三层结构”的Web应用程序,就好象是一家小餐馆。

    n            表 现 层,所有的.aspx页面就好像是这家餐馆的菜谱。

    n            中间业务层,就像是餐馆的服务生。

    n            数据访问层,就像是餐馆的大厨师傅。

    n            而我们这些网站浏览者,就是去餐馆吃饭的吃客了……

     

    我们去一家餐馆吃饭,首先得看他们的菜谱,然后唤来服务生,告诉他我们想要吃的菜肴。服务生记下来以后,便会马上去通知大厨师傅要烹制这些菜。大厨师傅收到通知后,马上起火烧菜。过了不久,服务生便把一道一道香喷喷的、热气腾腾的美味端到我们的桌位上——

    而我们访问一个基于asp.net技术的网站的时候,首先打开的是一个aspx页面。这个aspx页面的后台程序会去调用中间业务层的相应函数来获取结果。中间业务层又会去调用数据访问层的相应函数来获取结果。在一个用户访问TraceLWord3打开ListLWord.aspx页面查看留言的时候,其后台程序ListLWord.aspx.cs会去调用位于中间业务层LWordServiceListLWord(DataSet ds)函数。然后这个函数又会去调用位于数据访问层AccessTaskListLWord(DataSet ds)函数。最后把结果显示出来……

    对比一下示意图:

     

  • 相关阅读:
    python之集合(set)
    python之字典
    python之列表
    随笔
    JS实现颜色值格式转换 rgb和十六进制的转换
    20211025一周的计划
    密码肯定没错,但是你死活登录不了,登录页面检查密码格式不对,无法执行登录的一种解决方法
    安卓mbn文件丢失,无法搜索移动信号,工程模式mbn乱改,不用QPST烧录怎样恢复?超简单!
    安装Linux Deploy和Termux之后,再安装ftp服务软件都是多余的!
    “500 oops socket” Debian 9 running via Linux Deploy上成功部署vsftpd的解决方案(201901原创)【成功完美简单极致】
  • 原文地址:https://www.cnblogs.com/xbf321/p/880600.html
Copyright © 2011-2022 走看看