三层体系结构详细说明2

讲解1:DataManager 是D层中的一个类,提供常见的数据操作。GetOneColunm(string Table,string Colunm)方法返回一个只有1列的DataTable,值为数据库中表名为Table,的Colunm列。
public class DataManager
{
 public DataManager()
 {
 }
 public static DataTable GetOneColunm(string Table,string Colunm)
 {
  //此处省略相关代码。返回指定表指定列
 }
}
其实这个地方演示的是在U层直接绕过C层访问D层的例子,因为该结构逻辑上很简单,而且获取用户名并不是现实社会中的业务逻辑的一部分(仅仅是界面需要,因为在这里其实用成2个TextBox的话完全不需要这一步)
讲解2:定义一个User类的实例。User类的定义可能如下:
public class User
{
 public User(string uid)
 {
  if(DataManager.IsIn(“user”,”uid=’"+uid+”’”))
   throw "用户不存在";
  else
   //User()其他初始化;
 }
 public bool CheckPsw(string psw)
 {
  if(DataManager.IsIn(“user”,”uid=’"+uid+”’ and psw=’”+psw+”’”))
   return true;
  else
   return false;
 }
}
注意到用户类构造函数中用了个throw来抛出用户不存在的异常,在下面catch的时候用MessageBox(e. Message);来弹出“用户不存在”的错误。这里其实也是为了演示一个层间传递信息的手段,异常也是一种手段,虽然在这里其实可以有其他方式比如返回值,引用参数之类的直接用一个方法来获得用户是否存在的信息,没必要放在构造里,我这么做只是为了演示传递过程,在后面的有讨论这种用法在分层模式下某种特殊情况的应用以解决一些问题。这个类里又用了DataManager类的一个静态方法IsIn(string Table,string str)该方法其实其实是执行 “select * from Table where str”
这个Sql语句并在返回空的时候方法返回false,否则返回true。一个很简单的方法。这里演示了C层对D层的调用。
顺便说一句,因为在VS.Net中,项目的名称会默认地成为项目中的namespace,可以通过把所有自动生成的代码中的namespace改为“解决方案名称”来使3个层可以无缝地自由调用。或者在调用的地方using一下其他层的空间名,看个人喜欢了。比如上面的Login.aspx.cs里需要using2个,而User.cs里要using一个。
讲解3:这里的检查用户密码同样用到User类的一个方法CheckPsw()而这个方法 又用到了IsIn()这里就不多说了。
大家注意到我们在U层的页面里用MessageBox()方法来弹出对话框,其实这个方法写在PageBase.cs里,是U层的另外一个文件,继承Page类,Login类又继承它,这个方法其实是把Response.Write(“<script>alert(/“”+ msg+“/”)</script>”)封装起来了。
到此为止,登录结束,例子的实现也说完了。不过只讲了“然”,没有讲“所以然”。下面开始讲“所以然”。
第二部分
作为对比,我们使用一个不面向对象的,不分层的Asp式的Aspx相同登录作为对比。具体的Asp代码我就不写了,反正登录哪都有。先来看看他们2者发生的遭遇(这是不幸的,却偏偏是经常发生的):
1、  项目经理突然说“不用SqlServer了,换成Access”(正版费用问题)。看看2边分别发生什么:3层这边(A),把DataManager类里的连接改改(在实际情况下,极可能其实是改它的基类,它本身不用改),Web.config中把字符串换掉就完了。Asp式那边(B),同样要改Web.config,同样要改连接什么的,修改量在这个具体的“小溪”例子上几乎相同,在“大桥”例子上B应该会稍微多改点,不过也不会多很多。但是!请注意一点,我们在修改代码的时候,主要时间和精力不是花在“改”这个动作上,而是花在“要改什么地方”上和“寻找需要改的地方”上。在“大桥”上,B需要花费多的多的时间,对大部分文件进行查找和替换。A则仅仅在数据层里,另外2个层不需要任何修改。从这个角度出发我们想到2点原则:
a)    数据层必须要能够保证数据库的变动(任何结构变动、类型变动)对其余各层的不透明性。也就是数据库怎么变,其他层绝对不应该变哪怕1行代码!(web.config是整个应用程序的配置,虽然在物理上存在于U层的文件夹中,但个人更愿意认为它是独立的不属于任何层的,所以这里不计它)
b)    数据层越小越好(如果没有这点原则,我们把整个所有的东西都放在数据层,那当然数据库变动对外面无影响――因为外面几乎没东西――但是这显然不可行)。而且因为前面我们说了,大部分时间花在“找”上面,你小点,找起来也容易点。
2、  客户突然提出B/S版的不好,要换成C/S版的。对于(B)来说,这是晴天霹雳!!他的所有工作都要重新做,(或者几乎所有工作),虽然他有很多代码还可以用,不过他在未来一小段时间就必须不断在“复制-粘贴”中使用以前的代码。(A)发生了什么??如果你细心看会发现(A)之需要新建个项目“Windows用户界面”(和前面一样,添加引用,项目依赖),拖几个控件到上面,把控件名字起成txt,ddl,btn,然后把click代码和Pageload代码复制过去,(居然。。。)连1行代码都不需要修改!!!!当然,这是比较极端的例子(win和web都有TextBox,DropDownList,Button3种控件,而且我们在PageBase里定义的方法MessageBox()又刚好和win里面方法同名。。。)不过尽管有这么多巧合我们仍然可以也愿意相信,在“大桥”上,(A)将比(B)少做很多工作。从这个角度出发我们又想到2点类似原则:
a)    界面层应该保证界面的任何变化都不需要修改其他层的内容(不管这个具体的例子把ddl改为另外一个TextBox,或是把B/S改为C/S)
b)    界面层越小越好(理由同上。)
3、  除开了界面层和数据层,(如果你的方案中只有3个层的话)剩下的就都是逻辑层的内容了。所以和前面的相对应,我们可以得出结论:
a)    逻辑层应当不受数据库和界面变动的影响而需要修改。
b)    逻辑层越大越好(因为另外2层越小越好。。。)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值