• 你懂不懂我不知道,反正我是晕了


    这两天刚刚学了三层在网上找了点东西看看,看的有点晕



    <td id="text"><p>&nbsp;本文用一个示例来介绍如何建设一个三层架构的项目,并说明项目中各个文件所处的层次与作用。写本文的目的,不是为了说明自己的这个方法有多对,而是希望给那些初学三层架构却不知从何入手的朋友提供一点帮助。因为网上的文章,大多是注重理论的介绍,而忽略了具体的实践应用,或者有示例但讲得不透彻。导致看了之后,理论上又学习了一遍,但还是不知道代码怎么写。所以想从这个方面入手写一下,让从来没做过三层架构的初学者也能照猫画虎,写出代码来。文中的代码是伪代码,仅用来阐明思路。</p>
    <p>&nbsp;&nbsp;&nbsp; 正文:</p>
    <p>&nbsp;&nbsp;&nbsp; 一提三层架构,大家都知道是表现层(UI),业务逻辑层(BLL)和数据访问层(DAL),而且每层如何细分也都有很多的方法。但具体代码怎么写,到底那些文件算在哪一层,却是模模糊糊的。下面用一个简单的例子来带领大家实战三层架构的项目,这个例子只有一个功能,就是用户的简单管理。</p>
    <p>&nbsp;&nbsp;&nbsp; 首先建立一个空白解决方案,添加如下项目及文件</p>
    <p>&nbsp;&nbsp;&nbsp; 1、添加ASP.NET Web Application项目,命名为UI,新建Web Form类型文件User.aspx(含User.aspx.cs)</p>
    <p>&nbsp;&nbsp;&nbsp; 2、添加ClassLibrary项目,命名为BLL,新建Class类型文件UserBLL.cs</p>
    <p>&nbsp;&nbsp;&nbsp; 3、添加ClassLibrary项目,命名为DAL,新建Class类型文件UserDAL.cs。添加SQLHelper引用。(这个是微软的数据访问类,也可以不用,直接编写所有的数据访问代码。我一般用自己写的数据访问类DataAccessHelper )。</p>
    <p>&nbsp;&nbsp;&nbsp; 4、添加ClassLibrary项目,命名为Model,新建Class类型文件UserModel.cs</p>
    <p>&nbsp;&nbsp;&nbsp; 5、添加ClassLibrary项目,命名为IDAL,新建Interface类型文件IUserDAL.cs</p>
    <p>&nbsp;&nbsp;&nbsp; 6、添加ClassLibrary项目,命名为ClassFactory</p>
    <p>&nbsp;&nbsp;&nbsp; 相信大家已经看出来了,这个和Petshop的示例没什么区别,而且更简单,因为在下也是通过Petshop学习三层架构的。但一些朋友对于这几个项目所处的层次,以及它们之间的关系,可能比较模糊,这里逐个说明一下:</p>
    <p>&nbsp;&nbsp;&nbsp; 1、User.aspx和User.aspx.cs</p>
    <p>&nbsp;&nbsp;&nbsp; 这两个文件(以及文件所属的项目,下面也是如此,不再重复强调了)都属于表现层部分。User.aspx比较好理解,因为它就是显示页面了。User.aspx.cs有些人觉得不应该算,而是要划到业务逻辑层中去。如果不做分层的话,那么让User.aspx.cs来处理业务逻辑,甚至操作<a href=http://www.baoluowanxiang.com/database/ target=_blank class=infotextkey>数据库</a>都没什么问题,但是做分层的话,这样就不应该了。在分层结构中,User.aspx.cs仅应该处理与显示有关的内容,其它部分都不应该涉及。</p>
    <p>&nbsp;&nbsp;&nbsp; 举例:我们实现用列表方式显示用户的功能,那么提取信息的工作是由BLL来做的,UI(本例中是User.aspx.cs)调用BLL得到UserInfo后,通过代码绑定到User.aspx的数据控件上,就实现了列表的显示。在此过程中User.aspx.cs对UI没有起到什么作用,仅是用来传递数据,而且因为实际编码中大部分情况都是如此的实现,所以使有些人觉得User.aspx.cs不应该算UI,而应该并入BLL负责逻辑处理。继续往下看,这时提出了一个新需求,要求在每个用户的前面加一个图标,生动地表现出用户的性别,而且不满18岁的用儿童图标表示。这个需求的实现,就轮到User.aspx.cs来做了,这种情况下User.aspx.cs才算有了真正的用途。</p>
    <p>&nbsp;&nbsp;&nbsp; 2、NewBLL.cs</p>
    <p>&nbsp;&nbsp;&nbsp; 添加如下方法:</p>
    <p>&nbsp;&nbsp;&nbsp; public IList&lt;UserInfo&gt; GetUsers():返回所有的用户信息列表</p>
    <p>&nbsp;&nbsp;&nbsp; public UserInfo GetUser(int UserId):返回指定用户的详细信息</p>
    <p>&nbsp;&nbsp;&nbsp; public bool AddUser(UserInfo User):新增用户信息</p>
    <p>&nbsp;&nbsp;&nbsp; public bool ChangeUser(UserInfo User):更新用户信息</p>
    <p>&nbsp;&nbsp;&nbsp; public void RemoveUser(int UserId):移除用户信息</p>
    <p>&nbsp;&nbsp;&nbsp; 此文件就属于业务逻辑层了,专门用来处理与业务逻辑有关的操作。可能有很多人觉得这一层唯一的用途,就是把表现层传过来的数据转发给数据层。这种情况确实很多,但这只能说明项目比较简单,或者项目本身与业务的关系结合的不紧密(比如当前比较流行的MIS),所以造成业务层无事可做,只起到了一个转发的作用。但这不代表业务层可有可无,随着项目的增大,或者业务关系比较多,业务层就会体现出它的作用来了。</p>
    <p>&nbsp;&nbsp;&nbsp; 此处最可能造成错误的,就是把数据操作代码划在了业务逻辑层,而把数据库作为了数据访问层。</p>
    <p>&nbsp;&nbsp;&nbsp; 举例:有些朋友感觉BLL层意义不大,只是将DAL的数据提上来就转发给了UI,而未作任何处理。看一下这个例子</p>
    <p>&nbsp;&nbsp;&nbsp; BLL层</p>
    <p>&nbsp;&nbsp;&nbsp; SelectUser(UserInfo userInfo)根据传入的username或email得到用户详细信息。</p> <p>&nbsp;&nbsp;&nbsp; IsExist(UserInfo userInfo)判断指定的username或email是否存在。</p> <p>&nbsp;&nbsp;&nbsp; 然后DAL也相应提供方法共BLL调用</p> <p>&nbsp;&nbsp;&nbsp; SelectUser(UserInfo userInfo)</p> <p>&nbsp;&nbsp;&nbsp; IsExist(UserInfo userInfo)</p> <p>&nbsp;&nbsp;&nbsp; 这样BLL确实只起到了一个传递的作用。</p> <p>&nbsp;&nbsp;&nbsp; 但如果这样做:</p> <p>&nbsp;&nbsp;&nbsp; BLL.IsExist(Userinfo userinfo)</p> <p>&nbsp;&nbsp;&nbsp; {</p> <p>&nbsp;&nbsp;&nbsp; UerInfo user = DAL.SelectUser(User);</p> <p>&nbsp;&nbsp;&nbsp; return (userInfo.Id != null);</p> <p>&nbsp;&nbsp;&nbsp; }</p> <p>&nbsp;&nbsp;&nbsp; 那么DAL就无需实现IsExist()方法了,BLL中也就有了逻辑处理的代码。</p> <p>&nbsp;&nbsp;&nbsp; 3、UserModel.cs</p> <p>&nbsp;&nbsp;&nbsp; 实体类,这个东西,大家可能觉得不好分层。包括我以前在内,是这样理解的:UI?&agrave;Model?&agrave;BLL?&agrave;Model?&agrave;DAL,如此则认为Model在各层之间起到了一个数据传输的桥梁作用。不过在这里,我们不是把事情想简单,而是想复杂了。</p> <p>&nbsp;&nbsp;&nbsp; Model是什么?它什么也不是!它在三层架构中是可有可无的。它其实就是面向对象编程中最基本的东西:类。一个桌子是一个类,一条新闻也是一个类,int、string、doublie等也是类,它仅仅是一个类而已。</p> <p>&nbsp;&nbsp;&nbsp; 这样,Model在三层架构中的位置,和int,string等变量的地位就一样了,没有其它的目的,仅用于数据的<font color="#0000ff" size="3">存储</font>而已,只不过它<font color="#0000ff" size="3">存储</font>的是复杂的数据。所以如果你的项目中对象都非常简单,那么不用Model而直接传递多个参数也能做成三层架构。</p> <p>&nbsp;&nbsp;&nbsp; 那为什么还要有Model呢,它的好处是什么呢。下面是思考一个问题时想到的,插在这里:</p> <p>&nbsp;&nbsp;&nbsp; Model在各层参数传递时到底能起到做大的作用?</p> <p>&nbsp;&nbsp;&nbsp; 在各层间传递参数时,可以这样:</p> <p>&nbsp;&nbsp;&nbsp; AddUser(userId,userName,userPassword,&hellip;,)</p> <p>&nbsp;&nbsp;&nbsp; 也可以这样:</p> <p>&nbsp;&nbsp;&nbsp; AddUser(userInfo)</p> <p>&nbsp;&nbsp;&nbsp; 这两种方法那个好呢。一目了然,肯定是第二种要好很多。</p> <p>&nbsp;&nbsp;&nbsp; 什么时候用普通变量类型(int,string,guid,double)在各层之间传递参数,什么使用Model传递?下面几个方法:</p> <p>&nbsp;&nbsp;&nbsp; SelectUser(int UserId)</p> <p>&nbsp;&nbsp;&nbsp; SelectUserByName(string username)</p> <p>&nbsp;&nbsp;&nbsp; SelectUserByName(string username,string password)</p> <p>&nbsp;&nbsp;&nbsp; SelectUserByEmail(string email)</p> <p>&nbsp;&nbsp;&nbsp; SelectUserByEmail(string email,string password)</p> <p>&nbsp;&nbsp;&nbsp; 可以概括为:</p> <p>&nbsp;&nbsp;&nbsp; SelectUser(userId)</p> <p>&nbsp;&nbsp;&nbsp; SelectUser(user)</p> <p>&nbsp;&nbsp;&nbsp; 这里用user这个Model对象囊括了username,password,email这三个参数的四种组合模式。UserId其实也可以合并到user中,但项目中其它BLL都实现了带有id参数的接口,所以这里也保留这一项。</p> <p>&nbsp;&nbsp;&nbsp; 传入了userInfo,那如何处理呢,这个就需要按照先后的顺序了,有具体代码决定。</p> <p>&nbsp;&nbsp;&nbsp; 这里按这个顺序处理</p> <p>&nbsp;&nbsp;&nbsp; 首先看是否同时具有username和password,然后看是否同时具有email和password,然后看是否有username,然后看是否有email。依次处理。</p> <p>&nbsp;&nbsp;&nbsp; 这样,如果以后增加一个新内容,会员卡(number),则无需更改接口,只要在DAL的代码中增加对number的支持就行,然后前台增加会员卡一项内容的表现与处理即可。</p> <p>&nbsp;&nbsp;&nbsp; 4、UserDAL.cs</p> <p>&nbsp;&nbsp;&nbsp; public IList&lt;UserInfo&gt; SelectUsers():返回所有的用户信息列表</p> <p>&nbsp;&nbsp;&nbsp; public UserInfo SelectUser(int UserId):返回指定用户的相信信息</p> <p>&nbsp;&nbsp;&nbsp; public bool InsertUser(UserInfo User):新增用户信息</p> <p>&nbsp;&nbsp;&nbsp; public bool UpdateUser(UserInfo User):更新用户信息</p> <p>&nbsp;&nbsp;&nbsp; public void DeleteUser(int UserId):移除用户信息</p> <p>&nbsp;&nbsp;&nbsp; 很多人最闹不清的就是数据访问层,到底那部分才算数据访问层呢?有些认为数据库就是数据访问层,这是对定义没有搞清楚,DAL是数据访问层而不是数据存储层,因此数据库不可能是这一层的。也有的把SQLHelper(或其同类作用的组件)作为数据访问层,它又是一个可有可无的东西,SQLHelper的作用是减少重复性编码,提高编码效率,因此如果我习惯在乎效率或使用一个非数据库的数据源时,可以丢弃SQLHelper,一个可以随意弃置的部分,又怎么能成为三层架构中的一层呢。</p> <p>&nbsp;&nbsp;&nbsp; 可以这样定义:与数据源操作有关的代码,就应该放在数据访问层中,属于数据访问层</p> <p>&nbsp;&nbsp;&nbsp; 5、IUserDAL</p> <p>&nbsp;&nbsp;&nbsp; 数据访问层接口,这又是一个可有可无的东西,因为Petshop中带了它和ClassFactory类工厂,所以有些项目不论需不需要支持多数据源,都把这两个东西做了进来,有的甚至不建ClassFactory而只建了IDAL,然后&ldquo;IUserDAL iUserDal = new UserDAL();&rdquo;,不知意义何在。这就完全是画虎不成反类犬了。</p> <p>&nbsp;&nbsp;&nbsp; 许多人在这里有一个误解,那就是以为存在这样的关系:BLL?&agrave;IDAL?&agrave;DAL,认为IDAL起到了BLL和DAL之间的桥梁作用,BLL是通过IDAL来调用DAL的。但实际是即使你如此编码:&ldquo;IUserDAL iUserDal = ClassFacotry.CreateUserDAL();&rdquo;,那么在执行&ldquo;iUserDal.SelectUsers()&rdquo;时,其实还是执行的UserDAL实例,而不是IUserDAL实例,所以IDAL在三层中的位置是与DAL平级的关系。</p> <p>&nbsp;&nbsp;&nbsp; 通过上面的介绍,基本上将三层架构的层次结构说明了。其实,本人有一个判断三层架构是否标准的方法,那就是将三层中的任意一层完全替换,都不会对其它两层造成影响,这样的构造基本就符合三层标准了(虽然实现起来比较难^_^)。例如如果将项目从B/S改为C/S(或相反),那么除了UI以外,BLL与DAL都不用改动;或者将SQLServer改为<font color="#0000ff" size="3">Oracle</font>,只需替换SQLServerDAL到<font color="#0000ff" size="3">Oracle</font>DAL,无需其它操作等等。本来想在文中加入一些具体的代码的,但感觉不是很必要,如果大家觉得需要的话,我再补充吧。</p>
    <p>&nbsp;&nbsp;&nbsp; 总结:不要因为某个层对你来说没用,或者实现起来特别简单,就认为它没有必要,或者摒弃它,或者挪作它用。只要进行了分层,不管是几层,每一层都要有明确的目的和功能实现,而不要被实际过程所左右,造成同一类文件位于不同层的情况发生。也不要出现同一层实现了不同的功能的情况发生。</p> <p align="center" class="pageLink"></p></td>
  • 相关阅读:
    jmeter(46) redis
    jmeter(45) tcp/ip协议
    Codeforces Round #538 (Div. 2)D(区间DP,思维)
    Codeforces Global Round 1D(DP,思维)
    Educational Codeforces Round 57D(DP,思维)
    UPC11073(DP,思维)
    Yahoo Progamming Contest 2019D(DP,思维)
    Atcoder Beginner Contest 118D(DP,完全背包,贪心)
    Xuzhou Winter Camp 1C(模拟)
    Educational Codeforces Round 57 (Rated for Div. 2)D(动态规划)
  • 原文地址:https://www.cnblogs.com/lipengjiushiwo/p/2502642.html
Copyright © 2020-2023  润新知