经典三层 变 七层
机房总结
虽然自己的笔记还没有整理成博客,但是,我认为,作为第一遍重构完成的咱,首先要先写一下对机房整体的认知。
首先说这个三层 OR 七层
当时,话说是一个多月前,刚刚把三层的登陆实现,霍霍师傅来查看我的劳动成果,十分大方的表扬了我几句,后来给我说了一句话,我懵了——“你是打算先敲三层然后再转七层?还是直接用七层啊?” 我滴个乖乖,三层还没弄懂,怎么又出来个七层?什么是七层啊?什么又是三层啊?
皇天不负有心人,经过玉洋师傅的细心指导以及霍霍师傅的不厌其烦,我明白了
三层图:
这就是三层,看着怎么有四个啊?这是我的疑问!后来知道了,三层,主要分的是UI、BLL、DAL这三层,而实体层呢(Entity),是为了给三层解耦的,而整个三层都是为了给我们第一遍机房解耦来的
七层图:
这就是七层,貌似,我看到的是八层! 没错,你眼前的的这个SqlHelper,因为只有DAL引用他,所以有的人(我)就把它直接放在D层,作为了一个类,用来封装我们DAL层每个方法都要用到的几种SQL语句,果不其然,省了不少的事啊! 所以显而易见,所谓的七层,就是在三层的基础上加上了外观(Facade),接口(IDAL),工厂(Factory)
至于他们有什么用,咱们一会再说吧
那,咱们首先来看一下三层吧!
由上面的三层架构图大家应该就可以看出来作为显示层的UI和数据处理层的DAL是没有直接交互的,他们之间的所有联系都是由逻辑处理层BLL为枢纽进行的,就拿登陆来说:
1:在UI界面上输入自己的用户名和密码(然后把该相应的值赋给相应的实体)
2:根据实体层中相应实体的值作为条件DAL层去运用sql语句在数据库中进行查找,然后返回结果
3:接着就是Bll逻辑处理层的事了,BLL接受来自DAL返回的数据和UI传进来的数据进行处理,根据不同的条件返回给UI不同的答复,而这种返回时怎么实现的呢?就是自己为他们精心准备的方法Function,如例:
http://blog.csdn.net/liweizhong193516/article/details/43232215(vb.net实现三层登陆)
有了上面三层的底子,我们再来介绍七层就太简单了
同样,看上面七层的架构图,大家肯定会发现,其实UI和BLL和DAL和Entity的位置没有什么变化,只是在UI和BLL之间加上了Facade(外观),在BLL和DAL之间创建了一个接口IDAL,在外,又加了一个工厂,仅此而已。
首先我们说说外观Facade有什么用呢?
大家都学过设计模式了,大话设计模式里面的外观模式有什么用呢?————为子系统中的一组接口提供一个一致的界面
同样,我们这里的外观就是应用的设计模式,所以作用是相同的,将几个或者是N多个可以同时出现的东西统一起来,一起出现,省时省力啊,打个比方就比如你家一共有横排32盏灯,如果没一盏灯都有一个开关的话,那如果全开或者全关就得累死,所以,我们按了一个统一的开关,一按全开,一按全关(据实际情况而定)
只不过呢,在我的运用中,感觉外观用的不是很好,因为每个功能相对来说都比较独立,没有那么强的联系性,所以这个就没有代码展示了
我们再说说这个工厂吧,Factory+反射
Imports System.Configuration '添加对配置文件的引用 Imports System.Reflection '添加对反射的引用 Imports IDAL Public Class sqlFactory 将D层中的每个类都对应在配置文件中的Key值,下面只应用这个Key值就可以应用D层的类。这样D层的变化就不会修改Factory Dim strUSER As String = System.Configuration.ConfigurationSettings.AppSettings("strUSER") Public Function CreateIUser() As IUserInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strUSER), IUserInfo) End Function Dim strWL As String = System.Configuration.ConfigurationSettings.AppSettings("strWL") ''' <summary> ''' 工作记录工厂 ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Public Function CreateIWorkLog() As IWorkLog Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strWL), IWorkLog) End Function 'Dim strOnWL As String = System.Configuration.ConfigurationSettings.AppSettings("strOnWL") ' ''' <summary> ' ''' 正在工作工厂 ' ''' </summary> ' ''' <returns></returns> ' ''' <remarks></remarks> 'Public Function CreateIOnWorkLog() As IWorkLog ' Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strOnWL), IWorkLog) 'End Function ''' <summary> ''' 学生工厂 ''' </summary> ''' <remarks></remarks> Dim strStudent As String = System.Configuration.ConfigurationSettings.AppSettings("strStudent") Public Function CreateISdtudent() As IStudentInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strStudent), IStudentInfo) End Function ''' <summary> ''' 注册工厂 ''' </summary> ''' <remarks></remarks> Dim strCard As String = System.Configuration.ConfigurationManager.AppSettings("strCard") Public Function CreateIRegist() As IStudentInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strCard), IStudentInfo) End Function ''' <summary> ''' 定义D层数据设定表的配置文件相连 ''' </summary> ''' <remarks></remarks> Dim strBasicData As String = System.Configuration.ConfigurationSettings.AppSettings("strBasicData") Public Function CreateIBasicData() As IDataBasic Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strBasicData), IDataBasic) End Function ' ''' <summary> ' ''' 组合查询的工厂 ' ''' </summary> ' ''' <remarks></remarks> 'Dim strCombiStudentDB As String = System.Configuration.ConfigurationSettings.AppSettings("strCombiStudentDB") 'Public Function CreateICombination() As ICombination ' Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strCombiStudentDB), ICombination) 'End Function ''' <summary> ''' 充值工厂 ''' </summary> ''' <remarks></remarks> Dim strRecharge As String = System.Configuration.ConfigurationSettings.AppSettings("strRecharge") Public Function CreateIRecharge() As IRechargeInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strRecharge), IRechargeInfo) End Function ''' <summary> ''' 退卡工厂 ''' </summary> ''' <remarks></remarks> Dim strBackCard As String = System.Configuration.ConfigurationSettings.AppSettings("strBackCard") Public Function CreateIBackCard() As ICancelCardInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strBackCard), ICancelCardInfo) End Function ''' <summary> ''' 正在上机查询工厂 ''' </summary> ''' <remarks></remarks> Dim strOnLine As String = System.Configuration.ConfigurationSettings.AppSettings("strOnLine") Public Function CreateIOnLine() As IOnLineInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strOnLine), IOnLineInfo) End Function ''' <summary> ''' 上下机记录工厂 ''' </summary> ''' <remarks></remarks> Dim strOnOffLine As String = System.Configuration.ConfigurationSettings.AppSettings("strOnOffLine") Public Function CreateIOnOffLine() As ILineLog Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strOnOffLine), ILineLog) End Function ''' <summary> ''' 结账工厂 ''' </summary> ''' <remarks></remarks> Dim strSettleAccountDAL As String = System.Configuration.ConfigurationSettings.AppSettings("strSettleAccountDAL") Public Function CreateISettleAccount() As ICheck Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strSettleAccountDAL), ICheck) End Function End Class
这个是我们的app配置文件
<add name="UI.My.MySettings.MyChargeConnectionString" connectionString="Data Source=liweizhong;Initial Catalog=ReCharge_sys;User ID=sa;Password=li" providerName="System.Data.SqlClient" /> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <appSettings> <clear/> <add key="connString" value="server=liweizhong;database=ReCharge_sys;uid=sa;password=li;" /> <add key="strUSER" value="UserInfoDAO" /> <add key="strWL" value="WorkLogDAO" /> <add key="strOnWL" value="OnWorkLogDAO" /> <add key="strStudent" value="StudentInfoDAO" /> <add key="strCard" value="StudentInfoDAO" /> <add key="strBasicData" value="DataBasicDAO" /> <add key="strCombiStudentDB" value="CombinationDAO" /> <add key="strRecharge" value="RechargeInfoDAO" /> <add key="strBackCard" value="CancelCardInfoDAO" /> <add key="strOnLine" value="OnLineInfoDAO" /> <add key="strOnOffLine" value="LineLogDAO" /> <add key="strSettleAccountDAL" value="CheckDAO" /> </appSettings> </configuration>
通过上面大家可以看到什么呢?首先是工厂里面,一个个的小工厂,什么学生工厂啊,用户工厂什么的,想想设计模式里的工厂方法,应该理解不少吧。更加重要的来了,反射
大家可以看到,在配置文件里,各种各样的 Key value ,key是什么呢?钥匙?No,key是关键字,关键字又是在哪儿呢?看看工厂吧,这下大家明白了吧,在工厂里面定义关键字,确定该类要用的接口类,而转到UI层中的app配置文件中,根据关键字的不同来确定去拜访那个DAL,更加明显的的就是去看看操作哪张表。
其中值得一讲的是DAL的编译路径,要放到UI层上,不然会报错的哦,为什么呢?一头一尾总要在一条线上是吧
接口大家就很容易接受了吧,将DAL中的各个方法写好之后,不与外界联系,如果有谁要调用某个D层中的方法,就要调用IDAL中的接口,接口控制方法的使用,这样的话,如果感觉那个方法写得不好了或者不对,就不用每个层都改了,直接改D层就好了。
Public Interface IStudentInfo‘学生 接口 Function StudentLogin(ByVal Stu As Entity.StudentInfoEntity) As List(Of Entity.StudentInfoEntity) '学生登陆接口 Function SelectStudentInfo(ByVal Stu As Entity.StudentInfoEntity) As List(Of Entity.StudentInfoEntity) '选择学生接口 Function ChangePWD(ByVal Stu As Entity.StudentInfoEntity) As Integer '修改学生密码接口 Function Online(ByVal Stu As Entity.StudentInfoEntity) As Integer '查看在线学生接口 Function UpdateCash(ByVal Stu As Entity.StudentInfoEntity) As Integer '更新学生卡上余额接口 End Interface
而D层中呢,都有一个相应的方法与之对应
Public Class StudentInfoDAO : Implements IDAL.IStudentInfo Private SQLHelper As DAL.SQLhelper = New DAL.SQLhelper() Public Function StudentLogin(Stu As Entity.StudentInfoEntity) As List(Of Entity.StudentInfoEntity) Implements IStudentInfo.StudentLogin Dim List As New List(Of Entity.StudentInfoEntity) Dim table As DataTable Dim sql As String Dim sqlParams As SqlParameter() = {New SqlParameter("@IDcard", Stu.IDcard), New SqlParameter("@StuPWD", Stu.StuPWD)} sql = "select * from StudentInfo where IDcard=@IDcard and StuPWD=@StuPWD" table = SQLHelper.ExecSelect(sql, CommandType.Text, sqlParams) If table.Rows.Count > 0 Then List = ConvertListDAL.convertToList(Of Entity.StudentInfoEntity)(table) Return List Else Return Nothing End If End Function Public Function SelectStudentInfo(Stu As Entity.StudentInfoEntity) As List(Of Entity.StudentInfoEntity) Implements IStudentInfo.SelectStudentInfo Dim List As New List(Of Entity.StudentInfoEntity) Dim table As DataTable Dim sql As String Dim sqlPramas As SqlParameter() = {New SqlParameter("@IDcard", Stu.IDcard)} sql = "select * from [StudentInfo] where IDcard=@IDcard" table = SQLHelper.ExecSelect(sql, CommandType.Text, sqlPramas) If table.Rows.Count > 0 Then List = ConvertListDAL.convertToList(Of Entity.StudentInfoEntity)(table) Return List Else Return Nothing End If End Function Public Function ChangePWD(Stu As Entity.StudentInfoEntity) As Integer Implements IStudentInfo.ChangePWD Dim result As Integer Dim sql As String Dim sqlParams As SqlParameter() = {New SqlParameter("@IDcard", Stu.IDcard), New SqlParameter("@StuPWD", Stu.StuPWD)} sql = "update [StudentInfo] set StuPWD=@StuPWD where IDcard=@IDcard" result = SQLHelper.ExecAddDelUpdate(sql, CommandType.Text, sqlParams) Return result End Function Public Function Online(ByVal Stu As Entity.StudentInfoEntity) As Integer Implements IStudentInfo.Online Dim result As Integer Dim sql As String Dim sqlParams As SqlParameter() = {New SqlParameter("@IDcard", Stu.IDcard)} sql = "update [StudentInfo] set IsCheck='未结账' where IDcard=@IDcard" result = SQLHelper.ExecAddDelUpdate(sql, CommandType.Text, sqlParams) Return result End Function Public Function UpdateCash(Stu As Entity.StudentInfoEntity) As Integer Implements IStudentInfo.UpdateCash Dim result As Integer Dim sql As String Dim sqlParams As SqlParameter() = {New SqlParameter("@IDcard", Stu.IDcard), New SqlParameter("@Cash", Stu.Cash)} sql = "update [StudentInfo] set Cash=@Cash where IDcard=@IDcard" result = SQLHelper.ExecAddDelUpdate(sql, CommandType.Text, sqlParams) Return result End Function End Class
再加上七层之间的引用关系,大家应该明白了七层之间的逻辑了吧!
整个机房,耗时大约有一个月,从文档到验收,延期两次,整得自己战战兢兢,不过,学到的东西也不可同日而语,存储过程,视图的创建使用,模版,泛型,更加重要的是,显著培养了自己的调碼能力,最值得炫耀的事,就在这,我竟然看到好几次英文的材料,不是还没到这个阶段吗?更甚至,我竟然还看懂了一部分,获益良多啊
整体对机房先介绍这么多,下个月,我们接续