重构个人版机房收费系统——模板模式

来源:互联网 发布:大数据修仙 编辑:程序博客网 时间:2024/05/16 01:28

1、背景


在开始本篇博文之前,我们先来看一下下面截取的几幅图片:

1、组合查询

           


  2、根据卡号查询记录并导出到Excel表格

         


3、按照指定的时间范围查询记录


        是的,放眼望去,如果除去要实现的功能只考虑这三组图片的外观,那么每组的两张图片简直就是一个用模子刻出来的嘛~~~~~这就涉及到博文的主题了——模板模式。

2、模板模式

1、什么是模板模式

      模板模式,提供了一个代码复用平台,当不变和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现,形成了代码冗余,而且不易于维护,而模板模式就是把这些不变行为搬移到单一的地方(即超类),然后通过多态实现代码的复用。


2、机房收费实例讲解

      有了模板模式,最直观的一点好处就是再也不用花费很多时间在设置窗体界面上了(特别是组合查询),只要做个模子,直接“刻”就行啦~~。接下来就通过一个实例:学生上机信息查询,来增加一下理解。


1,首先正常添加windows窗体,并设置好模板窗体的界面。定义相关抽象类



抽象模板:

Imports EntityImports chargeManageBLLPublic Class frmGroupQuery    Protected enQueryGroup As New En_QueryGroup    ''' <summary>    ''' 窗体加载    ''' </summary>    ''' <param name="sender"></param>    ''' <param name="e"></param>    ''' <remarks></remarks>    Private Sub frmGroupQuery_Load(sender As Object, e As EventArgs) Handles MyBase.Load        '将参数传递给实体,赋初值        enQueryGroup.fileds1 = "1"        enQueryGroup.fileds2 = "1"        enQueryGroup.fileds3 = "1"        combOperA.Items.Add("=")        combOperA.Items.Add("<")        combOperA.Items.Add(">")        combOperA.Items.Add("<>")        combOperB.Items.Add("=")        combOperB.Items.Add("<")        combOperB.Items.Add(">")        combOperB.Items.Add("<>")        combOperC.Items.Add("=")        combOperC.Items.Add("<")        combOperC.Items.Add(">")        combOperC.Items.Add("<>")        combRelationA.Items.Add("与")        combRelationA.Items.Add("或")        combRelationB.Items.Add("与")        combRelationB.Items.Add("或")        '窗体加载,后两组控件默认为不可用        combFiledB.Enabled = False        combFiledC.Enabled = False        combOperB.Enabled = False        combOperC.Enabled = False        combRelationB.Enabled = False        txtContentB.Enabled = False        txtContentC.Enabled = False     End Sub    ''' <summary>    ''' 点击查询按钮,触发的事件    ''' </summary>    ''' <param name="sender"></param>    ''' <param name="e"></param>    ''' <remarks></remarks>    Private Sub btnSelect_Click(sender As Object, e As EventArgs) Handles btnSelect.Click        '不是组合查询        '限制输入条件不能为空        If combRelationA.Text = "" Then            If combFiledA.Text = "" Or combOperA.Text = "" Or txtContentA.Text = "" Then                MsgBox("查询条件不能为空,请填写完全!", vbOKOnly, "提示信息")                Exit Sub            End If        End If        '根据第一个组合查询条件文本内容是否为空判断下一组控件的内容是否为空        If combRelationA.Text <> "" Then            If combFiledA.Text = "" Or combOperA.Text = "" Or txtContentA.Text = "" Or combFiledB.Text = "" Or combOperB.Text = "" Or txtContentB.Text = "" Then                MsgBox("查询条件不能为空,请填写完全!", vbOKOnly, "提示信息")                Exit Sub            End If        End If        '根据第二个组合查询条件文本内容是否为空判断下一组控件的内容是否为空        If combRelationB.Text <> "" Then            If combFiledA.Text = "" Or combOperA.Text = "" Or txtContentA.Text = "" Or combFiledB.Text = "" Or combOperB.Text = "" Or txtContentB.Text = "" Or combFiledC.Text = "" Or combOperC.Text = "" Then                MsgBox("查询条件不能为空,请填写完全!", vbOKOnly, "提示信息")                Exit Sub            End If                  End If        Dim dt As New DataTable        Dim queryOperator As New F_GroupQuery          '实例化外观          '将参数传递给实体封装        enQueryGroup.fileds1 = GetEnglish(combFiledA.Text)        enQueryGroup.fileds2 = GetEnglish(combFiledB.Text)        enQueryGroup.fileds3 = GetEnglish(combFiledB.Text)        enQueryGroup.operator1 = combOperA.Text        enQueryGroup.operator2 = combOperB.Text        enQueryGroup.operator3 = combOperC.Text        enQueryGroup.content1 = txtContentA.Text.Trim        enQueryGroup.content2 = txtContentB.Text.Trim        enQueryGroup.content3 = txtContentC.Text.Trim        enQueryGroup.relation1 = combRelationA.Text.Trim        enQueryGroup.relation2 = combRelationB.Text.Trim        Dim strsql As String        strsql = SelectData()    End Sub    ''' <summary>    ''' 模板方法:定义虚函数GetEnglish,查询字段转化为数据库字段    ''' </summary>    ''' <param name="combField"></param>    ''' <returns></returns>    ''' <remarks></remarks>    Public Overridable Function GetEnglish(combField As String) As String        Return ""    End Function    ''' <summary>    ''' 定义虚函数GetTable,获取不同数据库的表名    ''' </summary>    ''' <returns></returns>    ''' <remarks></remarks>    Public Overridable Function GetTable() As String        Return ""    End Function    ''' <summary>    ''' 执行查询的关键函数    ''' </summary>    ''' <returns></returns>    ''' <remarks></remarks>    Protected Overridable Function SelectData()        Return ""    End Function    ''' <summary>    ''' 拼接字符串    ''' </summary>    ''' <param name="frm"></param>    ''' <returns></returns>    ''' <remarks></remarks>    Public Function Query(frm As frmGroupQuery) As String        Dim sql As String = "" & frm.GetEnglish(frm.combFiledA.Text) & frm.combOperA.Text & "'" & frm.txtContentA.Text & "'"        '非组合查询        If frm.combRelationA.Text = "" Then            sql = sql        Else            '第一个条件不为空,第二个条件为空            If frm.combRelationB.Text = "" Then                sql = sql & frm.GetEnglish(frm.combRelationA.Text) & " " & frm.GetEnglish(frm.combFiledB.Text) & frm.combOperB.Text & "'" & frm.txtContentB.Text & "'"            Else                '两个条件均不为空                sql = sql & frm.GetEnglish(frm.combRelationA.Text) & " " & frm.GetEnglish(frm.combFiledB.Text) & frm.combOperB.Text & "'" & frm.txtContentB.Text & "'" & "" & frm.GetEnglish(frm.combRelationB.Text) & " " & frm.GetEnglish(frm.combFiledC.Text) & frm.combOperB.Text & "'" & frm.txtContentC.Text & "'"            End If        End If        Return sql    End Function    ''' <summary>    ''' 第一个组合关系不为空    ''' </summary>    ''' <param name="sender"></param>    ''' <param name="e"></param>    ''' <remarks></remarks>    Private Sub combRelationA_SelectedIndexChanged(sender As Object, e As EventArgs) Handles combRelationA.SelectedIndexChanged        combFiledB.Enabled = True        combOperB.Enabled = True        txtContentB.Enabled = True        combRelationB.Enabled = True        combFiledC.Enabled = False        combOperC.Enabled = False        txtContentC.Enabled = False    End Sub    ''' <summary>    ''' 第二个组合关系不为空    ''' </summary>    ''' <param name="sender"></param>    ''' <param name="e"></param>    ''' <remarks></remarks>    Private Sub combRelationB_SelectedIndexChanged(sender As Object, e As EventArgs) Handles combRelationB.SelectedIndexChanged        combFiledC.Enabled = True        combOperC.Enabled = True        txtContentC.Enabled = True    End SubEnd Class

      设置完模板窗体后,接下来就是“刻”子窗体了。添加新项——继承的窗体,设置窗体名称,点击“添加”,在弹出的继承器窗口中选择要刚刚设置的模板窗体就Ok啦。




通过模板刻制出来的窗体,需要的排版、控件等等都与模板窗体完全一致,不错吧~~~




子类,实现父类所定义的一个或多个抽象方法。

<span style="font-size:14px;">Imports EntityImports chargeManageBLLPublic Class frmOnLine    Private Sub frmOnLine_Load(sender As Object, e As EventArgs) Handles MyBase.Load        combFiledA.Items.Add("卡号")        combFiledA.Items.Add("姓名")        combFiledA.Items.Add("上机日期")        combFiledA.Items.Add("上机时间")        combFiledA.Items.Add("下机日期")        combFiledA.Items.Add("下机时间")        combFiledA.Items.Add("消费金额")        combFiledA.Items.Add("余额")        combFiledB.Items.Add("卡号")        combFiledB.Items.Add("姓名")        combFiledB.Items.Add("上机日期")        combFiledB.Items.Add("上机时间")        combFiledB.Items.Add("下机日期")        combFiledB.Items.Add("下机时间")        combFiledB.Items.Add("消费金额")        combFiledB.Items.Add("余额")        combFiledC.Items.Add("卡号")        combFiledC.Items.Add("姓名")        combFiledC.Items.Add("上机日期")        combFiledC.Items.Add("上机时间")        combFiledC.Items.Add("下机日期")        combFiledC.Items.Add("下机时间")        combFiledC.Items.Add("消费金额")        combFiledC.Items.Add("余额")    End Sub    Public Overrides Function GetEnglish(combField As String) As String        Select Case combField            Case "卡号"                GetEnglish = "cardID"            Case "姓名"                GetEnglish = "studentName"            Case "上机日期"                GetEnglish = "onDate"            Case "上机时间"                GetEnglish = "onTime"            Case "下机日期"                GetEnglish = "offDate"            Case "下机时间"                GetEnglish = "offTime"            Case "消费金额"                GetEnglish = "consumeMoney"            Case "余额"                GetEnglish = "cash"            Case "与"                GetEnglish = "and"            Case "或"                GetEnglish = "or"            Case Else                GetEnglish = ""        End Select    End Function    Public Overrides Function GetTable() As String        Return "OnLine_table"    End Function    Protected Overrides Function SelectData() As Object        Dim dt As New DataTable        Dim facaonlineinfo As New F_GroupQuery        Dim frmgroupquery As New frmGroupQuery        Dim sql As String        Try            sql = frmgroupquery.Query(Me)            dt = facaonlineinfo.QueryOnLineInfo(sql)            If dt.Rows.Count = 0 Then                dt.Clear()                DataGridView1.DataSource = Nothing                DataGridView1.Refresh()            Else                DataGridView1.DataSource = dt                DataGridView1.Columns(0).Visible = False                DataGridView1.Columns(0).HeaderText = "卡号"                DataGridView1.Columns(1).HeaderText = "姓名"                DataGridView1.Columns(2).HeaderText = "上机日期"                DataGridView1.Columns(3).HeaderText = "上机时间"                DataGridView1.Columns(4).HeaderText = "下机日期"                DataGridView1.Columns(5).HeaderText = "下机时间"                DataGridView1.Columns(6).HeaderText = "消费金额"                DataGridView1.Columns(7).HeaderText = "余额"            End If        Catch ex As Exception            MsgBox(ex.Message, vbOKOnly, "提示信息")        End Try    End FunctionEnd Class</span>

        跟以往的类抽象不同的是,模板方法是一种反向的控制结构,这种结构有时被称为“好莱坞法则”,即“别找我们,我们找你”。这指的是一个父类调用一个子类的操作,而不是相反,在程序执行时进行跟踪即可验证。


       导出到Excel表格跟VB6.0有些不同,每个窗体都一样,所以该功能提炼到模板窗体中实现即可。

首先,设置datagridview控件的[AllowUserToAddRows]属性为False,否则会出现错误:未将对象引用到实例。

<span style="font-size:14px;">''' <summary>    ''' 导出到Excel    ''' </summary>    ''' <param name="sender"></param>    ''' <param name="e"></param>    ''' <remarks></remarks>    Private Sub btnExportExcel_Click(sender As Object, e As EventArgs) Handles btnExportExcel.Click        Dim MyExcel As New Excel.Application '添加工作簿        MyExcel.Application.Workbooks.Add()   '添加表        MyExcel.Visible = True   '打开表        '获取datagridview的标题行赋给Excel        'Excel标题行第一列标识为1,datagridview则为0,所以cols-1        Dim Cols As Integer        For Cols = 1 To DataGridView1.Columns.Count            MyExcel.Cells(1, Cols) = DataGridView1.Columns(Cols - 1).HeaderText        Next        '往Excel表中添加数据        Dim i As Integer        For i = 0 To DataGridView1.RowCount - 1            Dim j As Integer            For j = 0 To DataGridView1.ColumnCount - 1                If Me.DataGridView1(j, i).Value Is System.DBNull.Value Then                    MyExcel.Cells(i + 2, j + 1) = ""                Else                    MyExcel.Cells(i + 2, j + 1) = DataGridView1(j, i).Value.ToString()                End If            Next        Next</span>

        通过重构个人版机房收费,对部分设计模式有了更多的实际应用的机会,经过实战练习,在原来学习的基础上有了更深的理解。更多的知识还需要不断地去学习和积累。


0 0
原创粉丝点击