对于模板方法模式的使用,我后悔自己用晚了,因为我们的机房收费收费系统有很多窗体是几乎一样的,如果我们不用模板方法模式,就会大大增加工作量,首先,我们需要重复的创建窗体,其次我们的代码量也会大大增加,就是复制、粘贴代码也是一件让人摒弃的事情,所以推出模板方法模式,用意就在降低代码重复,减少工作量,通过求同存异的思想来实现。下面看一下我在组合查询中用到的模板方法模式:
首先,创建父窗体,父窗体的创建就是普通的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层与其他窗体都是一样的,在这里就不一一列出了。
设计模式学了很多种模式,可是真正去想的时候,也只是知道有这么个模式,至于怎么用,不知道,只有在敲机房的时候,使劲的加,才能体会到它的好处与不足,让知识活了起来!
重构机房收费系统之 模板方法模式,布布扣,bubuko.com
原文:http://blog.csdn.net/wangdan199112/article/details/27635721