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