【机房重构】——加入外观、工厂和接口的三层
2016-03-13 20:59
176 查看
前言
从传统的三层升七层,真的是拖了好长的时间揪其主要原因还是时间管理没有做好,其次就是个人的惰性。对于任何一个事物每个人都有不同的看法
下面我就和大家说一下我从三层到七层的一个转变过程
希望你也能找到一些同感
如果理解和代码有不到位的,还请大牛斧正。
正文
总览
所谓七层,就是在基本的三层中加入了外观和工厂模式,对应的加入了外观、接口和工厂。以及将原本的D层又抽象出了SqlHelper。附上一张盗的同学的七层的包图。
加入接口和工厂
在升七层之前,死心眼的我一直在问:为什么要加入工厂?(那是不清楚接口要和工厂一起使用)问题了同期的同学,给我的答案基本上都是,为了换数据库啊!无奈我也只能就这么接受了。
现有一个三层的登录例子(我最开始敲的)
发现原本的D层UserDAO类代码写的不优雅,并且效率很差;想要更换成一个代码优雅的userDal
那这个时候我们就必须对LoginBll类的代码进行一定的改动。
通过设计模式的学习,我们显然的知道这不是一种好的解决方案。
我们在追求的是更换D层UserDAO类时不更改B层任何代码,换句话说就是解除了B层和D层的耦合。
因此我们加入了IDAL接口类库
而此时在代码中,我们需要将B层原本对D层的引用更改为对IDAL的引用;
在D层中也要增加对IDAL的引用。
只要我们保证接口中方法的方法名不变,这样如何更换D层类,B层代码都不会受到影响
那现在我还有问题,工厂是做什么的?不要它行不行?为什么偏偏叫做工厂?
个人理解。
在B层中调用接口
1.接口不能实例化
2.所以就必须为其赋初值
3.为了解耦,就只能利用另一个类来给接口赋初值了
4.至于工厂,也不过是个名字而已,工厂也只不过是个类的名字罢了,用不用都行,只是这样比较让大家好接受
然后绕回来再说一句,为什么加工厂大家都说是为了换数据库?
因为换数据库和上面说的是一回事,同样是换D层类。
加入外观
在加外观之前就非常担心,感觉外观好难啊,我应该怎样加入到七层中呢?而将登录功能加上外观之后就感觉外观什么都没有。
小U拿个东西给我,然后我想都不用想直接给小B就行了。
感觉没有挑战性,就向注册窗体中加入外观。
开始时是一样的。
小U一个女生,背个大书包,而小B刚好受伤了拿不了东西。
小B需要东西,只能我去拿,然后递给小B;后来小U累了,书包太大,还得停下来等我拿东西,出于责任感,我一个大男人多拿点东西也没有什么。
现在小U轻松了,只需要将大书包给我,然后我拿着书包,小B需要东西,我直接给他就好了,不需要再去找小U了。
而注册卡号就是这种情况,需要先验证再添加。
之前是U层调外观调B,U层调外观调B;现在是U层调外观,外观调B,外观调B。
同样,像是有公主病的少女,有问题,我只找你,所有问题你必须解决。我只负责找你,其他的你去办就行了。
代码展示
下面是登录窗体的代码展示U层
Imports Facade Imports Entity Public Class frmLogin Dim strUserID As String Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click Dim user As New User_Info user.UserID = txtUserID.Text.Trim user.PassWord = txtPassWork.Text Dim fac As New facLogin txtPrompt.Text = fac.Test(user) If txtPrompt.Text = "" Then Me.Hide() frmMain.Show() End If End Sub End Class
外观
Imports BLL Imports Entity Public Class facLogin Public Function Test(ByVal user As User_Info) As String Dim Logbll As New LoginBll Return Logbll.Test(user) End Function End Class
B层
Imports IDAL Imports Entity Imports Factory Imports System.Data Imports System.Data.SqlClient Public Class LoginBll Dim dt As New DataTable REM 定义datatable对象 Dim log As ILogin REM 定义接口对象,接口不能实例化 Dim fac As New Factory.factory REM 实例化工厂 Public Function Test(ByVal user As User_Info) As String REM 前面是一些简单的逻辑判断 If user.UserID = "" Then Return "用户名不能为空" End If If user.PassWord = "" Then Return "密码不能为空" End If log = fac.Logfactory REM 接口不能实例化必须通过第三个类给接口赋初值 dt = log.selectUser(user) REM 调用接口中的方法 Try user.UserID = dt.Rows(0).Item(0) user.Level = dt.Rows(0).Item(3) log.AddWork(user) Return "" Catch ex As Exception Return "用户名或密码错误" End Try End Function End Class
接口
Imports Entity Public Interface ILogin Function selectUser(ByVal user As User_Info) As DataTable Function AddWork(ByVal user As User_Info) As Integer End Interface
D层
Imports System.Data Imports System.Data.SqlClient Imports SqlHelper Imports Entity Imports IDAL Public Class SqlLoginDal : Implements ILogin Public Function AddWork(user As User_Info) As Integer Implements ILogin.AddWork Dim strLogindate As String = Date.Today Dim strLogintime As String = TimeOfDay Dim helper As New SqlHelper.sqlhelper Dim cmdText As String = "INSERT INTO onwork_info VALUES (@userid,@level,@logindate,@logintime,@computer)" Dim sqlParams As SqlParameter() = {New SqlParameter("@userid", user.UserID), New SqlParameter("@level", user.Level), New SqlParameter("@logindate", strLogindate), New SqlParameter("@logintime", strLogintime), New SqlParameter("@computer", Environment.GetEnvironmentVariable("COMPUTERNAME"))} Return helper.ExecuteNonQuery(cmdText, CommandType.Text, sqlParams) End Function ''' <summary> ''' 登录窗体检测用户名密码是否正确 ''' </summary> ''' <param name="user"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function selectUser(user As User_Info) As DataTable Implements ILogin.selectUser Dim strUserID As String = user.UserID Dim strPassWord As String = user.PassWord Dim cmdText As String = "SELECT * FROM user_info WHERE userid=@userid and password =@password" Dim sqlParams As SqlParameter() = {New SqlParameter("@userid", strUserID), New SqlParameter("@password", strPassWord)} Dim dt As New DataTable Dim helper As New SqlHelper.sqlhelper dt = helper.ExecuteQuery(cmdText, CommandType.Text, sqlParams) Return dt End Function End Class
实体层
Public Class User_Info Private _userid As String Private _password As String Private _username As String Private _level As String Private _head As String Property UserID As String Get Return _userid End Get Set(value As String) _userid = value End Set End Property Property PassWord As String Get Return _password End Get Set(value As String) _password = value End Set End Property Property UserName As String Get Return _username End Get Set(value As String) _username = value End Set End Property Property Level As String Get Return _level End Get Set(value As String) _level = value End Set End Property Property Head As String Get Return _head End Get Set(value As String) _head = value End Set End Property End Class
总结
任何事情,光是停留在想象上面,永远是困难的,犹如蜀道然而只要勇敢迈出第一步,又如探囊取物。
相关文章推荐
- Fragment的使用(三)
- ajax重定向问题
- 第一章读书笔记
- coreboot学习2:项目源码的初步了解
- 客户端文件上传分享
- u-boot的配置
- DRIVER_OBJECT,DEVICE_OBJECT 结构体分析
- GSON源码解析
- ecshop登录超时、session过期的解决办法
- MongoDB学习—(6)MongoDB的find查询比较符
- css 实现垂直居中的常用方法
- Fragment小结
- 开源数据库连接池之C3P0
- 通用树的存储结构
- python笔记之字符串格式化
- CSS样式的优先级
- Hdu 2073 无限的路【数学】
- 第二天复习多线程的笔记整理
- Android 双击返回键退出应用程序
- TComponent,TControl,TWinControl,TGraphic的DefineProperties赏析与说明(不懂)