打印

[asp.net教程] 浅谈“三层结构”原理与用意 6

浅谈“三层结构”原理与用意 6

用户在访问tracelword3的listlword.aspx页面时序图:
   
   
   
   
   
   
  当一个用户访问tracelword5的listlword.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.0和duwamish7的研究,并不是本文的重点。现在的问题就是:既然“三层结构”已经被分派到各自的项目中,那么剩下来的项目是做什么的呢?例如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会去调用位于中间业务层lwordservice的listlword(dataset ds)函数。然后这个函数又会去调用位于数据访问层accesstask的listlword(dataset ds)函数。最后把结果显示出来……
   

   
   
  对比一下示意图:
   
   
   
   
   
   
  从示意图看,这两个过程是否非常相似呢?
   
   
   
  不同的地方只是在于,去餐馆吃饭,需要吃客自己唤来服务生。而访问一个asp.net网站,菜单可以代替吃客唤来服务生。在最后的返回结果上,把结果返回给aspx页面,也就是等于把结果返回给浏览者了。
   
   
   
  高度的“面向对象思想”的体现——封装
   
  在我们去餐馆吃饭的这个过程中,像我这样在餐馆中的吃客,最关心的是什么呢?当然是:餐馆的饭菜是不是好吃,是不是很卫生?价格是不是公道?……而餐馆中的服务生会关心什么呢?应该是:要随时注意响应每位顾客的吩咐,要记住顾客在哪个桌位上?还要把顾客点的菜记在本子上……餐馆的大厨师傅会关心什么呢?应该是:一道菜肴的做法是什么?怎么提高烧菜的效率?研究新菜式……大厨师傅,烧好菜肴之后,只管把菜交给服务生就完事了。至于服务生把菜送到哪个桌位上去了?是哪个顾客吃了他做的菜,大厨师傅才不管咧——服务生只要记得把我点的菜肴端来,就成了。至于这菜是怎么烹饪的?顾客干麻要点这道菜?他才不管咧——而我,只要知道这菜味道不错,价格公道,干净卫生,其他的我才不管咧——
   
  这里面不正是高度的体现了“面向对象思想”的“封装”原则吗?
   
  无论大厨师傅在什么时候研究出新的菜式,都不会耽误我现在吃饭。就算服务生忘记我的桌位号是多少了,也不可能因此让大厨师傅忘记菜肴的做法?在我去餐馆吃饭的这个过程中,我、餐馆服务生、大厨师傅,是封装程度极高的三个个体。当其中的一个个体内部发生变化的时候,并不会波及到其他个体。这便是面向对象封装特性的一个益处!
   
   
   
  土豆炖牛肉盖饭与实体规范
   
    在我工作过的第一家公司楼下,有一家成都风味的小餐馆,每天中午我都和几个同事一起去那家小餐馆吃饭。公司附近只有这么一家餐馆,不过那里的饭菜还算不错。我最喜欢那里的“土豆炖牛肉盖饭”,也很喜欢那里的“鸡蛋汤”,那种美味至今难忘……所谓“盖饭”,又称是“盖浇饭”,就是把烹饪好的菜肴直接遮盖在铺在盘子里的米饭上。例如“土豆炖牛肉盖饭”,就是把一锅热气腾腾的“土豆炖牛肉”遮盖在米饭上——
   
   
   
  当我和同事再次来到这家餐馆吃饭,让我们想象以下这样的情形:
   
   
   
  情形一:
   
  我对服务生道:给我一份好吃的!
   
  服务生道:什么好吃的?
   
  我答道:一份好吃的——
   
  三番几次……
   
  我对服务生大怒道:好吃的,好吃的,你难道不明白吗?!——
   
   
   
  这样的情况是没有可能发生的!因为我没有明确地说出来我到底要吃什么?所以服务生也没办法为我服务……
   
  问题后果:我可能被送往附近医院的精神科……
   
   
   
  情形二:
   
  我对服务生道:给我一份土豆炖牛肉盖饭!
   
  服务生对大厨师傅道:做一份宫爆鸡丁——
   
   
   
  这样的情况是没有可能发生的!因为我非常明确地说出来我要吃土豆炖牛肉盖饭!但是服务生却给我端上了一盘宫爆鸡丁?!
   
  问题后果:我会投诉这个服务生的……
   
   
   
  情形三:
   
  我对服务生道:给我一份土豆炖牛肉盖饭!
   
  服务生对大厨师傅道:做一份土豆炖牛肉盖饭——
   
  大厨师傅道:宫爆鸡丁做好了……
   
   
   
  这样的情况是没有可能发生的!因为我非常明确地说出来我要吃土豆炖牛肉盖饭!服务生也很明确地要求大厨师傅做一份土豆炖牛肉盖饭。但是厨师却烹制了一盘宫爆鸡丁?!
   
  问题后果:我会投诉这家餐馆的……
   
   
   
  情形四:
   
  我对服务生道:给一份土豆炖牛肉盖饭!
   
  服务生对大厨师傅道:做一份土豆炖牛肉盖饭——
   
  大厨师傅道:土豆炖牛肉盖饭做好了……
   
  服务生把盖饭端上来,放到我所在的桌位。我看着香喷喷的土豆炖牛肉盖饭,举勺下口正要吃的时候,却突然发现这盘土豆炖牛肉盖饭变成了石头?!
   
   
   
  这样的情况更是没有可能发生的!必定,现实生活不是《西游记》。必定,这篇文章是学术文章而不是《哈里波特》……
   
  问题后果:……
   
   
   
  如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在tracelword3这个项目中呢?似乎上面这些荒唐的事情都成真了。(我想,不仅仅是在tracelword3这样的项目中,作为这篇文章的读者,你是否也经历过像这一样荒唐的项目而全然未知呢?)
   
   
   
  首先在listlword.aspx.cs文件
   
   
   
   
   
  ...
   
  #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 }
   
  ...
   
   
   
    在listlword.aspx.cs文件中,使用的是dataset对象来取得留言板信息的。但是dataset是不明确的!为什么这么说呢?行#051由lwordservice填充的dataset中可以集合任意的数据表datatable,而在这些被收集的datatable中,不一定会有一个是我们期望得到的。假设,lwordservice类中的listlword函数其函数内容是:
   
   
   
  ...
   
  #006 namespace tracelword3.interservice
   
  #007 {
   
  ...
   
  #011 public class lwordservice
   
  #012 {
   
  ...
   
  #019 public int listlword(dataset ds, string tablename)
   
  #020 {
   
  #021 ds.tables.clear();
   
  #022 ds.tables.add(new datatable(tablename));
   
  #023
   
  #024 return 1;
   
  #025 }
   
  ...

TOP

返回顶部
AYBlue

Processed in 0.052118 second(s), 7 queries.

当前时区 GMT+8, 现在时间是 2009-1-10 12:08 京ICP备06054220号

清除 Cookies - 联系我们 - 163K.com - Archiver - WAP