机房收费系统=三层+设计模式

   在简单的三层登陆完成之后,我又在其中加入了设计模式,其中包括抽象工厂+反射和外观模式.关于设计模式,在学习三层之前我们已经系统的学习过,可是在这次往机房收费系统中加设计模式时,还是感觉无从下手,出现了学没有致用的尴尬情景.不过这也体现了我们提高班学习中项目驱动的优势.

   接下来是我的一些现有思路,可能还不很准确,期待读者朋友的指点.

   先说一下简单的三层登陆思想吧:

   我们现阶段接触的三层就是最基本的三层--UI,BLL层和DAL.关于这三者之间的关系,在我前面博客中有所涉及,如果有兴趣,你可以参看:三层架构入门

   言归正传,理论知识我们知道了,在机房收费系统中,我们究竟是如何利用这三层来简化灵活我们的代码的呢?(由于.NET版本的登陆已经加入设计模式,所以简单三层C#语言来展示.)

   大家可以先看下主体代码:

   UI: 代码如下:

private void btnOK_Click(object sender, EventArgs e)
        {
            UserInfo user = new UserInfo();
            //向实体层传递参数
            string UserName = txtUserName.Text.Trim();
            string Password = txtPassword.Text.Trim();
            user.UserName=UserName ;
            user.Password = Password;
            //实例化BLL层,并调用BLL层方法
            LoginManager mgr = new LoginManager();
            UserInfo user2 = new UserInfo();
            user2 = mgr.UserLogin(user);
            MessageBox.Show("登录用户:" + user.UserName);
        }

   U,就是我们窗体类,是用户唯一可以看到的部分.其中不涉及连接数据库,也不会包括业务逻辑.它主要负责接收用户输入指令并传给实体类,再有实体类传给B,进行业务逻辑的判断.同时它也会根据B层产生的不同结果来及时反馈给用户.


   BLL: 代码如下:

public  class LoginManager
    {
        public UserInfo UserLogin(UserInfo user)
        {
            //实例化DAL层,并调用DAL层方法
            UserDAO uDAO = new UserDAO();
            user = uDAO.SelectUser(user  );
            //逻辑判断代码
            if (user != null)
            {
                ScoreDAO sDAO = new ScoreDAO();
                sDAO.UpdateScore(user, 10);
                return user;
            }
            else
            {
                throw new Exception("登录失败!");
            }
        }

   这一层是业务逻辑层,顾名思义,它主要负责系统中的绝大部分逻辑判断,一旦U层或者D层出现业务逻辑判断,我们就要考虑,它是不是应该放在B.


   DAl: 代码如下:

namespace Login.DAL
{
     public  class UserDAO
    {
         /// <summary>
         /// 连接数据库,获取用户信息
         /// </summary>
         /// <param name="user">用户信息实体</param>
         /// <returns>用户信息</returns>
        public UserInfo  SelectUser(UserInfo user)
        {        
            using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))   //有待填写
            {
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = @"SELECT ID, UserName,Password,Email from Users where UserName=@UserName and Password=@Password";
                cmd.CommandType = CommandType.Text;
                
                cmd.Parameters.Add(new SqlParameter ("@UserName",user.UserName  ));
                cmd.Parameters.Add(new SqlParameter ("@Password",user.Password ));
                conn.Open();

                SqlDataReader reader = cmd.ExecuteReader();
                user=null;
                while (reader .Read ())//Read()方法:读取一个表的记录
                {
                    if (user == null)
                    {
                        user = new UserInfo();
                    }
                    user.ID = reader.GetInt32(0);
                    user.UserName = reader.GetString(1);
                    user.Password = reader.GetString(2);
                    if (!reader.IsDBNull(3)) 
                    {
                        user.Email = reader.GetString(3);
                    }
                }
                return user;    
            }
        }
    }
}

   从以上的代码就可以看出,D层主要是连接数据库,从数据库中读取信息,然后再以实体的形式传给B,B层传给U,最后表现在用户面前.

 

   上述是没有添加设计模式的简单三层登陆,下面就要谈一谈为什么要加设计模式,以及如何添加设计模式了.

   设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结.使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。也许这样说读者还是不大明白,下面的代码展示或许可以给您一些启示.

   首先说一下抽象工厂+反射,在机房登录中的应用(只展示主体代码,方便理解).

   Abstract Factory: 抽象工厂接口,它里面包含所有产品创建的抽象方法.工厂类被BLL层调用,并调用IDAL接口,使用配置文件读取数据库字符串.通过反射技术,解除简单工厂更换数据库时的分支判断带来的耦合.

   代码如下:

Imports System.Configuration
Imports System.Reflection
Imports IDAL

Public Class SqlFactory
    Private Shared ReadOnly AssemblyName As String = "DAL"
    '使用配置文件,读取数据库连接字符
    Private Shared DB As String = ConfigurationManager.AppSettings("strDB")

#Region "获取用户信息"
    Public Shared Function CreatGetUserInfo() As IDAL.IGetUserInfo
        Dim UserInfo As IGetUserInfo
        Dim ClassName As String
        '反射技术,解除简单工厂更换数据库时的分支判断带来的耦合
        ClassName = AssemblyName + "." + DB + "D_GetUserInfo"
        UserInfo = CType(Assembly.Load(AssemblyName).CreateInstance(ClassName), IDAL.IGetUserInfo)
        Return UserInfo
    End Function
#End Region

   IDAL接口:  B层和D层调用,使得B层和D层的耦合度极大降低.

Imports Entity

Public Interface IGetUserInfo
    Function GetUserInfo(ByVal e_Users As Entity.E_UserInfoEntity) As DataTable
End Interface

   BLL:  定义接口类,并使用工厂类SqlFactory方法反射实例化相应的DAl.这时候B层和D层已经完全不再耦合,B层或者D层的任何变动,都不会影响另一层.(这就是我们使用抽象工厂加反射的最大用处了.)

Imports Entity
Imports IDAL
Imports DBFactory.SqlFactory
Imports DAL

Public Class B_UserInfo
    '创建工厂类,作用:创建接口对象
    Public SqlFactory As New DBFactory.SqlFactory
#Region "验证用户密码"
    Public Function VerifyPassword(ByVal EUserInfo As E_UserInfoEntity) As Boolean

        '创建获得用户信息的接口
        Dim IGetPWD As IDAL.IGetUserInfo
        IGetPWD = DBFactory.SqlFactory.CreatGetUserInfo
        Dim dtUserInfo As DataTable
        dtUserInfo = IGetPWD.GetUserInfo(EUserInfo)

        If dtUserInfo.Rows.Count = 0 Then
            Throw New Exception("该用户还未注册!")
            Return False
        End If

        '判断密码是否正确
        If EUserInfo.Passwrod = Trim(dtUserInfo.Rows(0).Item(1)) Then
            Return True
        Else
            Return False
        End If
    End Function
#End Region
End Class

   抽象工厂和反射解耦和B层和D层.接下来的外观模式就要解耦U层和B层了.

   Facade类: 在简单的三层中,界面层的登陆需要根据B层返回的值再进行判断,这样B层和U层的耦合度是比较高的.而加入外观模式后,上面提到的对B层返回值进行判断就可以移到外观类中.这样就充分实现了B层和U层的分离.

Imports Entity
Imports BLL

Public Class Login
    Private bUserInfo As New B_UserInfo
    Dim blnFlag As Boolean = False
    ''' <summary>
    ''' 对B层的返回值进行逻辑判断
    ''' </summary>
    ''' <param name="eUserInfo">用户信息实体</param>
    ''' <returns>用户信息正确返回True,错误返回False</returns>
    ''' <remarks></remarks>
    Public Function IsPassword(ByVal eUserInfo As E_UserInfoEntity) As Boolean
        Try
            blnFlag = bUserInfo.VerifyPassword(eUserInfo)
        Catch ex As Exception
            MsgBox(ex.Message, vbOKOnly, "提示信息")
        End Try

        If blnFlag = True Then
            Return True
        Else
            MsgBox("密码错误,请重新输入!")
            Return False
        End If
    End Function
End Class

   UI:   外观层在对B层返回值进行判断之后,返回信息给UI层.这样U层和B层就实现了分离,两者中任何一层发生变化都不用修改另一层的代码.

Imports Entity
Imports BLL
Imports Facade.Login


Public Class frmLogin
    Public bUserInfo As New B_UserInfo
    Public faUserInfo As New Facade.Login

    Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
        Dim aUserInfo As New Entity.E_UserInfoEntity
        Dim blnFlag As Boolean = False

        aUserInfo.UserID = Trim(txtUserName.Text)
        aUserInfo.Passwrod = Trim(txtPassword.Text)

        '调用外观类的IsPassword方法进行逻辑判断
        Try
            blnFlag = faUserInfo.IsPassword(aUserInfo)
        Catch ex As Exception
            MsgBox(ex.Message, vbOKOnly, "提示信息")
        End Try

        If blnFlag = True Then
            frmMain.Show()
        End If
    End Sub
End Class

   上述是我现阶段对三层和部分设计模式的理解,错误之处希望读者朋友多多指教!


  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 43
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值