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

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

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

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

我们现阶段接触的三层就是最基本的三层--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


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


你可能感兴趣的:(设计模式)