欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > windows >内容正文

windows

机房收费系统之抽象工厂篇

发布时间:2025/6/15 windows 45 豆豆
生活随笔 收集整理的这篇文章主要介绍了 机房收费系统之抽象工厂篇 小编觉得挺不错的,现在分享给大家,帮大家做个参考.


    机房收费系统vb.net个人版已完成,在此过程中分层的好处在系统的完成过程中得到了很好的体会。第一遍用的是纯三层做的,这几天又在此基础上又重构了登录的demo,加上抽象工厂和配置文件的使用。下面以登录功能为例,总结一下我的机房收费系统。

一、下面看一下我的包图:

      可以看到,这张图是从最基本的三层UI→BLL→DAL加入设计模式(抽象工厂)演化而来的,采用抽象工厂是考虑到日后更换数据库的方便。

 

二、准备工作

       创建数据表(课参见实体类中的代码)

       创建相应的类库和窗体。

       我用的是vb.net的WidowsApplication来添加界面;使用类库作为其它层的包。

 

三、抽象各层的类

        当我们确定了系统的整体架构,就要从宏观到微观的实现。

3.1 Entity(实体层)

        数据库设计好了,我们要根据数据库中的表抽象实体类,系统中,实体类和表基本上是一一对象的。一个表映射一个实体类,表的字段即为实体类的属性。

        实体层并不属于三层的任何一层,它是独立出来的一层,可以把它看做是自定义变量的组合,供其它三层使用。

[vb] view plaincopyprint?
  • Public Class UserInfoEntity  
  •  
  • #Region "定义UserInfo表中各个属性变量"  
  •     Private _userName As String  
  •     Private _name As String  
  •     Private _password As String  
  •     Private _userlevel As String  
  •     Private _accountHolder As String  
  •     Private _regDate As String  
  •     Private _regTime As String  
  • #End Region  
  •  
  • #Region "定义数据表中各个字段名常量"  
  •     Private Const DBFLELD_USERNAME = "userName"  
  •     Private Const DBFLELD_NAME = "name"  
  •     Private Const DBFLELD_PASSWORD = "password"  
  •     Private Const DBFLELD_USERLEVEL = "userLevel"  
  •     Private Const DBFLELD_ACCOUNTHOLDER = "accountHolder"  
  •     Private Const DBFLELD_REGDATE = "regDate"  
  •     Private Const DBFLELD_TIME = "regTime"  
  • #End Region  
  •  
  • #Region "定义数据表中各个字段参数变量"  
  •     Public Const DBPARAM_USERNAME = "@userName"  
  •     Public Const DBPARAM_NAME = "@name"  
  •     Public Const DBPARAM_PASSWORD = "@password"  
  •     Public Const DBPARAM_USERLEVEL = "@userLevel"  
  •     Public Const DBPARAM_ACCOUNTHOLDER = "@accountHolder"  
  •     Public Const DBPARAM_REGDATE = "@regDate"  
  •     Public Const DBPARAM_TIME = "@regTime"  
  • #End Region  
  •   
  •     ''' <summary>  
  •     ''' 获取数据表中的一条记录  
  •     ''' </summary>  
  •     ''' <param name="dr">字段名</param>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Public Sub LoadFromDataRow(ByVal dr As DataRow)  
  •         userName = dr(DBFLELD_USERNAME)  
  •         name = dr(DBFLELD_NAME)  
  •         password = dr(DBFLELD_PASSWORD)  
  •         userlevel = dr(DBFLELD_USERLEVEL)  
  •         accountHolder = dr(DBFLELD_ACCOUNTHOLDER)  
  •         regDate = dr(DBFLELD_REGDATE)  
  •         regTime = dr(DBFLELD_TIME)  
  •     End Sub  
  •  
  • #Region "填充一条记录"  
  •     ''' <summary>  
  •     ''' 填充一条记录(登录)到实体层  
  •     ''' </summary>  
  •     ''' <param name="AuserName">用户名</param>  
  •     ''' <param name="Apassword">密码</param>  
  •     ''' <param name="AuserLevel">用户级别</param>  
  •     ''' <remarks>2013-5-9 by liu hai yan </remarks>  
  •     Public Overloads Sub Fill(ByVal AuserName As StringByVal Apassword As StringByVal AuserLevel As String)  
  •         userName = AuserName  
  •         password = Apassword  
  •         userlevel = AuserLevel  
  •     End Sub  
  • #End Region  
  •  
  • #Region "定义数据表中各个属性"  
  •     ''' <summary>  
  •     ''' 用户名  
  •     ''' </summary>  
  •     ''' <value></value>  
  •     ''' <returns></returns>  
  •     ''' <remarks></remarks>  
  •     Public Property userName() As String  
  •         Get  
  •             Return _userName  
  •         End Get  
  •         Set(ByVal value As String)  
  •             _userName = value  
  •         End Set  
  •     End Property  
  •   
  •     ''' <summary>  
  •     ''' 用户姓名  
  •     ''' </summary>  
  •     ''' <value></value>  
  •     ''' <returns></returns>  
  •     ''' <remarks></remarks>  
  •     Public Property name() As String  
  •         Get  
  •             Return _name  
  •         End Get  
  •         Set(ByVal value As String)  
  •             _name = value  
  •         End Set  
  •     End Property  
  •   
  •     ''' <summary>  
  •     ''' 用户密码  
  •     ''' </summary>  
  •     ''' <value></value>  
  •     ''' <returns></returns>  
  •     ''' <remarks></remarks>  
  •     Public Property password() As String  
  •         Get  
  •             Return _password  
  •         End Get  
  •         Set(ByVal value As String)  
  •             _password = value  
  •         End Set  
  •     End Property  
  •   
  •     ''' <summary>  
  •     ''' 用户权限  
  •     ''' </summary>  
  •     ''' <value></value>  
  •     ''' <returns></returns>  
  •     ''' <remarks></remarks>  
  •     Public Property userlevel() As String  
  •         Get  
  •             Return _userlevel  
  •         End Get  
  •         Set(ByVal value As String)  
  •             _userlevel = value  
  •         End Set  
  •     End Property  
  •   
  •     ''' <summary>  
  •     ''' 开户人  
  •     ''' </summary>  
  •     ''' <value></value>  
  •     ''' <returns></returns>  
  •     ''' <remarks></remarks>  
  •     Public Property accountHolder() As String  
  •         Get  
  •             Return _accountHolder  
  •         End Get  
  •         Set(ByVal value As String)  
  •             _accountHolder = value  
  •         End Set  
  •     End Property  
  •   
  •     ''' <summary>  
  •     ''' 注册日期  
  •     ''' </summary>  
  •     ''' <value></value>  
  •     ''' <returns></returns>  
  •     ''' <remarks></remarks>  
  •     Public Property regDate() As String  
  •         Get  
  •             Return _regDate  
  •         End Get  
  •         Set(ByVal value As String)  
  •             _regDate = value  
  •         End Set  
  •     End Property  
  •   
  •     ''' <summary>  
  •     ''' 注册时间  
  •     ''' </summary>  
  •     ''' <value></value>  
  •     ''' <returns></returns>  
  •     ''' <remarks></remarks>  
  •     Public Property regTime() As String  
  •         Get  
  •             Return _regTime  
  •         End Get  
  •         Set(ByVal value As String)  
  •             _regTime = value  
  •         End Set  
  •     End Property  
  • #End Region  
  •   
  • End Class  
  •  

           下面是配置文件的使用:在窗体层添加新项目→选中打开窗口的左边的General选项→添加配置文件,(中间部分是需要手动添加的)。

    [vb] view plaincopyprint?
  • <?xml version="1.0" encoding="utf-8" ?>  
  • <configuration>  
  •   
  •     <appSettings >  
  •         <add key="connStr" value ="Data Source=.;Initial Catalog=Login;User ID=sa;Password=123456"/>  
  •         <add key ="AssemblyName" value ="DAL"/>  
  •         <add key ="db" value ="DB"/>  
  •     </appSettings>  
  •   
  •     <startup>  
  •         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" />  
  •     </startup>  
  • </configuration>  
  •  

    3.2 DAL层(数据访问层)

        接下来我们再看一下数据访问层(DAL),这一层的主要任务是直接操作数据库,完成对数据的增删改查等。这里我们仍然根据数据表来抽象DAL层的类,基本上也是一个表对应一个类,这样当我们增加新的表,直接增加新的DAL层类就可以,很好地符合了“开闭原则”。

    另外,因为DAL层的类是直接对数据库进行操作的类,所以这个类里封转大都有四种方法:增删改查。但根据实际情况会有不同的参数,不同的返回值。

           这里添加了接口层IDAL,利用反射和抽象工厂,以防更换数据库。

    3.2.1 接口层IDAL,添加Entity的引用。

    [vb] view plaincopyprint?
  • Imports Entity  
  •   
  • Public Interface Iuser  
  •     ''' <summary>  
  •     ''' 查看一条记录是否存在  
  •     ''' </summary>  
  •     ''' <param name="entityUser">用户信息</param>  
  •     ''' <returns>一条用户记录</returns>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Function Check(ByVal entityUser As UserInfoEntity) As UserInfoEntity  
  • End Interface  
  •  

    3.2.2 DAL层实现IDAL接口

            下面是DAL层下的DataAccess类

            添加Configuration引用时需从.net子项目中查找,还要添加项目引用Entity和IDAL.

    [vb] view plaincopyprint?
  • '如果没有使用配置文件加反射,不用引用Configuration和Reflection  
  • Imports System.Configuration  
  • Imports System.Reflection  
  • Imports System.Data.SqlClient  
  • Imports Entity  
  • Imports IDAL  
  •   
  • Public Class DataAccess  
  •  
  • #Region "连接数据库"  
  •     Private ReadOnly connStr As String = ConfigurationManager.AppSettings("connStr")  
  •     ''' <summary>  
  •     ''' 创建一个数据库连接  
  •     ''' </summary>  
  •     ''' <returns></returns>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Public Overloads Function CreateConn() As SqlConnection  
  •         Return New SqlConnection(connStr)  
  •     End Function  
  • #End Region  
  •  
  • #Region "关闭相关对象"  
  •     ''' <summary>  
  •     ''' 关闭SqlConnection对象  
  •     ''' </summary>  
  •     ''' <param name="conn">连接数据库</param>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Public Sub Close(ByVal conn As SqlConnection)  
  •         conn.Close()  
  •         conn = Nothing  
  •     End Sub  
  •   
  •     ''' <summary>  
  •     ''' 关闭SqlCommand对象  
  •     ''' </summary>  
  •     ''' <param name="cmd">sql命令</param>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Public Sub Close(ByVal cmd As SqlCommand)  
  •         cmd.Dispose()  
  •         cmd = Nothing  
  •     End Sub  
  • #End Region  
  •   
  •     ''' <summary>  
  •     ''' 为sql变量赋值并添加到SqlCommand中  
  •     ''' </summary>  
  •     ''' <param name="cmd">SqlCommand命令</param>  
  •     ''' <param name="dbParam">参数名</param>  
  •     ''' <param name="dbType">参数类型</param>  
  •     ''' <param name="value">参数值</param>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Public Sub AddSqlParameter(ByVal cmd As SqlCommand, ByVal dbParam As StringByVal dbType As SqlDbType, ByVal value As Object)  
  •         Dim sqlParam As SqlParameter = New SqlParameter(dbParam, dbType)  
  •         sqlParam.Value = value  
  •         cmd.Parameters.Add(sqlParam)  
  •     End Sub  
  •   
  • End Class  
  •  

            DAL层下的DBuser类

            同样添加项目引用Entity和IDAL.

    [vb] view plaincopyprint?
  • Imports System.Data.SqlClient  
  • Imports Entity  
  • Imports IDAL  
  •   
  • Public Class DBuser  
  •     '前面BLL没有用抽象工厂的这里不用继承DataAccess  
  •     Inherits DataAccess  
  •     Implements Iuser  
  •   
  •     Public Function Check(ByVal entityUser As Entity.UserInfoEntity) As UserInfoEntity Implements IDAL.Iuser.Check  
  •         '这里的sql语句是为了以后的灵活性,将各个字段使用了常量来进行表示,具体可参见实体层  
  •         Dim sql As String = String.Format("select * from userInfo where [userName]={0} and [password]={1} and [userLevel]={2}", UserInfoEntity.DBPARAM_USERNAME, UserInfoEntity.DBPARAM_PASSWORD, UserInfoEntity.DBPARAM_USERLEVEL)  
  •         Dim conn As SqlConnection = CreateConn()  
  •         Dim cmd As SqlCommand = New SqlCommand(sql, conn)  
  •         Dim sda As SqlDataAdapter = New SqlDataAdapter(cmd)  
  •         Dim ds As New DataSet  
  •   
  •         '向cmd中添加参数  
  •         AddSqlParameter(cmd, UserInfoEntity.DBPARAM_USERNAME, SqlDbType.VarChar, entityUser.userName)  
  •         AddSqlParameter(cmd, UserInfoEntity.DBPARAM_PASSWORD, SqlDbType.VarChar, entityUser.password)  
  •         AddSqlParameter(cmd, UserInfoEntity.DBPARAM_USERLEVEL, SqlDbType.VarChar, entityUser.userlevel)  
  •   
  •         Try  
  •             conn.Open()  
  •             sda.Fill(ds, "userInfo")  
  •             Dim dr As DataRow = ds.Tables("userInfo").Rows(0)  
  •             entityUser.LoadFromDataRow(dr)  
  •             Return entityUser  
  •         Catch ex As Exception  
  •             Return Nothing  
  •         Finally  
  •             Close(cmd)  
  •             Close(conn)  
  •         End Try  
  •     End Function  
  • End Class  
  •  

          抽象工厂+反射+配置文件

    [vb] view plaincopyprint?
  • Imports System.Configuration  
  • Imports System.Reflection  
  • Imports IDAL  
  •   
  • Public Class Factory  
  •  
  • #Region "配置加反射"  
  •     Private Shared ReadOnly AssemblyName As String = ConfigurationManager.AppSettings("AssemblyName")  
  •     Private Shared ReadOnly db As String = ConfigurationManager.AppSettings("db")  
  •     ''' <summary>  
  •     ''' 实例化Iuser类型的DBuser类对象  
  •     ''' </summary>  
  •     ''' <returns>DBuser类对象</returns>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Public Shared Function CreateUser() As Iuser  
  •         Dim ClassName As String  
  •         ClassName = AssemblyName + "." + db + "user"  
  •         Return CType(Assembly.Load(AssemblyName).CreateInstance(ClassName), Iuser)  
  •     End Function  
  • #End Region  
  •   
  • End Class  


  • 3.BLL层(封装业务层):前提添加DAL,IDAL和Entity的引用

    [vb] view plaincopyprint?
  • Imports IDAL  
  • Imports Entity  
  • Imports Factory  
  •   
  • Public Class BllLogin  
  •     ''' <summary>  
  •     ''' 查看登录信息是否存在  
  •     ''' </summary>  
  •     ''' <param name="entityUserInfo">窗体输入的用户信息</param>  
  •     ''' <returns>登录是否成功</returns>  
  •     ''' <remarks>2013-5-9 by liuhaiyan</remarks>  
  •     Public Function CheckRecord(ByVal entityUserInfo As UserInfoEntity) As Boolean  
  •         Dim checkResult As Boolean  
  •         '下面声明的iuser是实例化的Iuser类型的DBuser,实现了接口的调用(接口虽然不能被实例化,但是继承它的类可实例化成接口类型)  
  •         Dim iuser As Iuser  
  •         '此处运用的是抽象工厂设计模式中的反射加配置,如果没有用设计模式可以讲下面的这句话改为:iuser=new DBuser()  
  •         iuser = Factory.Factory.CreateUser()  
  •   
  •         If Not IsNothing(iuser.Check(entityUserInfo)) Then  
  •             checkResult = True  
  •         Else  
  •             checkResult = False  
  •         End If  
  •   
  •         Return checkResult  
  •     End Function  
  • End Class  
  • 4.UI层(界面层)

             界面层的类,就是我们窗体类,又多少个 窗体,UI层就有多少个类。

            下面我们看一下登录窗体类。

    [vb] view plaincopyprint?
  • Imports BLL  
  • Imports Entity  
  •   
  • Public Class frmLogin  
  •     '登录  
  •     Private Sub btnLogin_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnLogin.Click  
  •         '判断文本框是否为空  
  •         If txtUserID.Text = "" Then  
  •             MessageBox.Show("用户名不能为空!")  
  •             txtUserID.Focus()  
  •             Return  
  •         End If  
  •   
  •         If txtPassword.Text = "" Then  
  •             MessageBox.Show("用户名不能为空!")  
  •             txtPassword.Focus()  
  •             Return  
  •         End If  
  •   
  •         '填充参数记录(此处调用的是实体层中实体类userInfo中的填充记录Fill方法,后面会有介绍)  
  •         Dim entityUserInfo As New UserInfoEntity  
  •         entityUserInfo.Fill(Trim(txtUserID.Text), Trim(txtPassword.Text), Trim(cboUserLevel.Text))  
  •   
  •         '验证用户记录(调用BLL层中的验证用户记录CheckRecord方法)  
  •         Dim bllUserInfo As New BllLogin  
  •         If bllUserInfo.CheckRecord(entityUserInfo) Then  
  •             Me.Hide()  
  •             frmMain.Show()  
  •   
  •             '判断用户级别  
  •             ' ……  
  •             '添加用户记录  
  •             ' ……  
  •         Else  
  •             MsgBox("登录失败", vbOKOnly + vbInformation, "登录失败")  
  •             txtUserID.Focus()  
  •             Exit Sub  
  •         End If  
  •     End Sub  
  •   
  •     '取消  
  •     Private Sub btnCancel_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnCancel.Click  
  •         Me.Close()  
  •     End Sub  
  •   
  • End Class  
  •      

            上面就是我在三层(UI→BLL→DAL)的基础上加上设计模式抽象工程实现系统登录的Demo,拿出来和大家一起分享,其中的不足之处,还希望大家多多指正。


    总结

    以上是生活随笔为你收集整理的机房收费系统之抽象工厂篇的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。