閱讀371 返回首頁    go 技術社區[雲棲]


重構機房收費係統之 模板方法模式

            對於模板方法模式的使用,我後悔自己用晚了,因為我們的機房收費收費係統有很多窗體是幾乎一樣的,如果我們不用模板方法模式,就會大大增加工作量,首先,我們需要重複的創建窗體,其次我們的代碼量也會大大增加,就是複製、粘貼代碼也是一件讓人摒棄的事情,所以推出模板方法模式,用意就在降低代碼重複,減少工作量,通過求同存異的思想來實現。下麵看一下我在組合查詢中用到的模板方法模式:

          首先,創建父窗體,父窗體的創建就是普通的winform,我們知道組合查詢這塊兒一共有四個窗體是大同小異的:學生上機狀態查看、上機信息統計、學生基本信息維護、操作員工作記錄,他們的窗體(包括控件)是一致的,除字段名和要查詢的內容不一樣,其餘都一樣,所以要用到重寫,在每個子窗體中根據本窗體的需要而有所不同:下麵看一下父窗體的代碼:        

Imports Entity
Imports Facade
Public Class frnMulSelection
    Protected enMulSelection As New MulSelectionEntity
    ''' <summary>
    ''' 查詢
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnQuery_Click(sender As Object, e As EventArgs) Handles btnQuery.Click
        Try
            '如果第一個連接條件為空
            If cboConnection1.Text.Trim = "" Then
                Dim arrayControl() As Control
                ReDim Preserve arrayControl(2)

                arrayControl(0) = cboFields1
                arrayControl(1) = cboOperator1
                arrayControl(2) = txtContent1
                '判斷第一行是否為空
                If IsSomeEmptyText(arrayControl) = True Then
                    Exit Sub
                End If
                SelectData()
            Else
                If cboConnection2.Text.Trim = "" Then
                    Dim arrayControl() As Control
                    ReDim Preserve arrayControl(6)

                    arrayControl(0) = cboFields1
                    arrayControl(1) = cboOperator1
                    arrayControl(2) = txtContent1
                    arrayControl(3) = cboConnection1
                    arrayControl(4) = cboFields2
                    arrayControl(5) = cboOperator2
                    arrayControl(6) = txtContent2
                    '判斷第一行是否為空
                    If IsSomeEmptyText(arrayControl) = False Then
                        Exit Sub
                    End If
                Else
                    '如果關係1和2都不為空,判斷控件內容是否為空
                    If IsAllEmptyText(Me) = False Then
                        Exit Sub
                    End If
                End If
            End If
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Exclamation, "提示")
        End Try     
    End Sub
    ''' <summary>
    ''' 字段名
    ''' </summary>
    ''' <param name="getFields"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>

    Public Overridable Function sqlFields(ByVal getFields As String) As String
        Return ""
    End Function

    ''' <summary>
    ''' 獲取表名
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overridable Function GetTable() As String
        Return ""
    End Function


    ''' <summary>
    ''' 拚接字符串
    ''' </summary>
    ''' <param name="frm"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Query(frm As frnMulSelection) As String
        Dim strConnection As String '拚接字符串
        '如果第一個鏈接條件為空
        If frm.cboConnection1.Text = "" Then
            strConnection = " " & sqlFields(frm.cboFields1.Text) & frm.cboOperator1.Text & " '" & frm.txtContent1.Text & "'"
        Else
            '如果第一個不為空,第二個為空
            If Me.cboConnection2.Text = "" Then
                strConnection = " " & sqlFields(Me.cboFields1.Text) & Me.cboOperator1.Text & " '" & Me.txtContent1.Text & "'" &
                    sqlFields(Me.cboConnection1.Text) & " " & sqlFields(Me.cboFields2.Text) & Me.cboOperator2.Text & "'" & Me.txtContent2.Text & "'"
            Else
                '如果兩個鏈接條件都不為空
                strConnection = " " & sqlFields(Me.cboFields1.Text) & Me.cboOperator1.Text & " '" & Me.txtContent1.Text & "'" &
                    sqlFields(Me.cboConnection1.Text) & " " & sqlFields(Me.cboFields2.Text) & Me.cboOperator2.Text & "'" & Me.txtContent2.Text & "'" &
                    sqlFields(Me.cboConnection2.Text) & " " & sqlFields(Me.cboFields3.Text) & Me.cboOperator3.Text & "'" & Me.txtContent3.Text & "'"
            End If
        End If
        Return strConnection
    End Function
    ''' <summary>
    ''' 執行查詢的關鍵函數
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Overridable Function SelectData()
        Return ""
    End Function


    ''' <summary>
    ''' 退出
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
        Me.Dispose()
    End Sub

    Private Sub frnMulSelection_Load(sender As Object, e As EventArgs) Handles Me.Load
        '將每個表共同的操作符提取出來
        btnMofify.Visible = False
        cboOperator1.Items.Add("=")
        cboOperator1.Items.Add("<")
        cboOperator1.Items.Add(">")
        cboOperator1.Items.Add("<>")

        cboOperator2.Items.Add("=")
        cboOperator2.Items.Add("<")
        cboOperator2.Items.Add(">")
        cboOperator2.Items.Add("<>")

        cboOperator3.Items.Add("=")
        cboOperator3.Items.Add("<")
        cboOperator3.Items.Add(">")
        cboOperator3.Items.Add("<>")

        'cboConnection1.SelectedIndex = 1
        cboConnection1.Items.Add("")
        cboConnection1.Items.Add("與")
        cboConnection1.Items.Add("或")
        'cboConnection2.SelectedIndex = 1
        cboConnection2.Items.Add("")
        cboConnection2.Items.Add("與")
        cboConnection2.Items.Add("或")
        '在父窗體中填充選項
        enMulSelection.Fields1 = "1"
        enMulSelection.Fields2 = "1"
        enMulSelection.Fields3 = "1"
        enMulSelection.Operator1 = "="
        enMulSelection.Operator2 = "="
        enMulSelection.Operator3 = "="
        enMulSelection.Content1 = "1"
        enMulSelection.Content2 = "1"
        enMulSelection.Content3 = "1"
        enMulSelection.Connection1 = "and"
        enMulSelection.Connection2 = "and"
        '在一開始的時候,隻允許第一個條件行可用,隻有選擇了連接關係後,其他下麵的條件行在可以用
        cboFields2.Enabled = False
        cboOperator2.Enabled = False
        txtContent2.Enabled = False
        cboConnection2.Enabled = False
        cboFields3.Enabled = False
        cboOperator3.Enabled = False
        txtContent3.Enabled = False

    End Sub
    ''' <summary>
    ''' 如果選擇了第一個連接調節,則第二個條件行也可以寫入
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub cboConnection1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboConnection1.SelectedIndexChanged
        cboFields2.Enabled = True
        cboOperator2.Enabled = True
        txtContent2.Enabled = True
        cboConnection2.Enabled = True
    End Sub
    ''' <summary>
    ''' 同上
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub cboConnection2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboConnection2.SelectedIndexChanged
        cboFields3.Enabled = True
        cboOperator3.Enabled = True
        txtContent3.Enabled = True

    End Sub
    ''' <summary>
    '''用於學生信息維護中的修改學生信息時選中某行修改,是虛函數
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Public Overridable Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick

    End Sub
End Class
          子窗體是這樣繼承的:

          

         點擊“添加”後,選擇要繼承的父窗體:

         

          下麵是子窗體的代碼:         

Imports Facade '導入外觀
Imports Entity '導入實體
Public Class frmMulWorkLog
    Private Sub frmMulWorkLog_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        cboFields1.Items.Add("教師")
        cboFields1.Items.Add("注冊日期")
        cboFields1.Items.Add("注冊時間")
        cboFields1.Items.Add("注銷日期")
        cboFields1.Items.Add("注銷時間")
        cboFields1.Items.Add("機器號")

        cboFields2.Items.Add("教師")
        cboFields2.Items.Add("注冊日期")
        cboFields2.Items.Add("注冊時間")
        cboFields2.Items.Add("注銷日期")
        cboFields2.Items.Add("注銷時間")
        cboFields2.Items.Add("機器號")

        cboFields3.Items.Add("教師")
        cboFields3.Items.Add("注冊日期")
        cboFields3.Items.Add("注冊時間")
        cboFields3.Items.Add("注銷日期")
        cboFields3.Items.Add("注銷時間")
        cboFields3.Items.Add("機器號")

    End Sub
    Protected Overrides Function SelectData() As Object

        Dim facWorkLog As New WorkLogFacade
        Dim dtWorkLog As New DataTable
        Dim frmmulworklog As New frmMulWorkLog


        Dim strConnection As String
        strConnection = frmmulworklog.Query(Me) '此處用到了多態,把子類傳給父類,重寫父類的方法。

        Try
            dtWorkLog = facWorkLog.SelectMulWork(strConnection)
            If dtWorkLog.Rows.Count <= 0 Then
                dtWorkLog.Clear() '清空datatable中上次的記錄
                DataGridView1.DataSource = Nothing '使表中的數據為空
                DataGridView1.Refresh() '重新繪製表
            Else
                DataGridView1.DataSource = dtWorkLog
                DataGridView1.Columns(0).Visible = False
                DataGridView1.Columns(0).HeaderText = "序列號"
                DataGridView1.Columns(1).HeaderText = "教師"
                DataGridView1.Columns(2).Visible = False
                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, MsgBoxStyle.Exclamation, "提示")
        End Try

    End Function
    Public Overrides Function sqlFields(getFields As String) As String

        Select Case getFields
            Case "序列號"
                Return "serious"
            Case "教師"
                Return "UserName"
            Case "用戶級別"
                Return "UserLevel"
            Case "注冊日期"
                Return "LogOnDate"
            Case "注冊時間"
                Return "LogOnTime"
            Case "注銷日期"
                Return "LogOffDate"
            Case "注銷時間"
                Return "LogOffTime"
            Case "機器號"
                Return "機器號"
            Case "或"
                Return "Or"
            Case "與"
                Return "And"
            Case Else
                Return ""
        End Select

    End Function
    Public Overrides Function GetTable() As String
        enMulSelection.Table = "T_WorkLog"
        Return "T_WorkLog"
    End Function
End Class
           子窗體的代碼很簡單,就是對不同的地方進行了重寫,其他的隻需要繼承父窗體就可以了,至於外觀層、B層、D層與其他窗體都是一樣的,在這裏就不一一列出了。

            設計模式學了很多種模式,可是真正去想的時候,也隻是知道有這麼個模式,至於怎麼用,不知道,隻有在敲機房的時候,使勁的加,才能體會到它的好處與不足,讓知識活了起來!

         



最後更新:2017-04-03 08:26:19

  上一篇:go 解讀順豐優選背後王衛布局的一盤大棋
  下一篇:go 連載:麵向對象葵花寶典:思想、技巧與實踐(33) - ISP原則