【机房个人重构】组合查询--模板方法

时间:2022-09-16 11:18:21

      在第一次做机房收费系统的时候,有一大“难题”就是组合查询,有3个框架相同的窗体,基本同样的功能,在机房重构的时候,用到模板方法来进行对组合查询的实现,这种方法很方便也很高效,同样,其中也涉及到一些有用的知识,下面我来梳理一下组合查询是如何实现的。


【功能概况】

  【机房个人重构】组合查询--模板方法

    有3个这样的窗体,都是类似的功能和窗体界面,当一件事情重复3遍的时候,我们就要好好思考一下,如何减轻代码量,实现高效率。那么,下面我来说说模板方法的具体应用。


【具体实现】

    首先,先建立一个窗体当模板。

    【机房个人重构】组合查询--模板方法

     里面的代码如下:

   

Public Class frmGroupQuery
    '定义一个实体来传递参数,同7层其他窗体    Public egroupquery As New Entity.GroupQueryInfo
    '查询按钮下的代码,做逻辑判断    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click        DataGridView1.AllowUserToAddRows = False        If cmbRelation1.Text = "" Then            If cmbField1.Text = "" Then                MsgBox("请输入字段名")                Exit Sub            ElseIf cmbOperation1.Text = "" Then                MsgBox("请输入操作符")                Exit Sub            ElseIf txtContent1.Text = "" Then                MsgBox("请输入要查询的内容")                Exit Sub            End If        End If        If cmbRelation1.Text <> "" Then            If cmbField1.Text = "" Then                MsgBox("请输入第一行字段名")                Exit Sub            ElseIf cmbOperation1.Text = "" Then                MsgBox("请输入第一行操作符")                Exit Sub            ElseIf txtContent1.Text = "" Then                MsgBox("请输入第一行要查询的内容")                Exit Sub            ElseIf cmbField2.Text = "" Then                MsgBox("请输入第二行字段名")                Exit Sub            ElseIf cmbOperation2.Text = "" Then                MsgBox("请输入第二行操作符")                Exit Sub            ElseIf txtContent2.Text = "" Then                MsgBox("请输入第二行要查询的内容")                Exit Sub            End If        End If        If cmbRelation2.Text <> "" Then            If cmbField1.Text = "" Then                MsgBox("请输入字段名")            ElseIf cmbOperation1.Text = "" Then                MsgBox("请输入操作符")            ElseIf txtContent1.Text = "" Then                MsgBox("请输入要查询的内容")            ElseIf cmbField2.Text = "" Then                MsgBox("请输入字段名")            ElseIf cmbOperation2.Text = "" Then                MsgBox("请输入操作符")            ElseIf txtContent2.Text = "" Then                MsgBox("请输入要查询的内容")            ElseIf cmbField3.Text = "" Then                MsgBox("请输入字段名")            ElseIf cmbOperation3.Text = "" Then                MsgBox("请输入操作符")            ElseIf txtContent3.Text = "" Then                MsgBox("请输入要查询的内容")            End If        End If        <pre name="code" class="vb" style="font-size: 24px;">        '定义一个实体参数 
Dim egroupquery As New Entity.GroupQueryInfo  

 
        'GetDBName在这里是用了下面的虚方法(可以在子窗体重写)
egroupquery.cmbFied1 = GetDBName(cmbField1.Text.Trim)
egroupquery.cmbFied2 = GetDBName(cmbField2.Text.Trim)
egroupquery.cmbFied3 = GetDBName(cmbField3.Text.Trim)
egroupquery.cmbOperation1 = cmbOperation1.Text.Trim
egroupquery.cmbOperation2 = cmbOperation2.Text.Trim
egroupquery.cmbOperation3 = cmbOperation3.Text.Trim
egroupquery.txtContent1 = txtContent1.Text.Trim
egroupquery.txtContent2 = txtContent2.Text.Trim
egroupquery.txtContent3 = txtContent3.Text.Trim
egroupquery.cmbRelation1 = GetDBName(cmbRelation1.Text.Trim)
egroupquery.cmbRelation2 = GetDBName(cmbRelation2.Text.Trim)
         '这里的GetTable也是一个虚方法的使用        egroupquery.GetTable = GetTable()        '经典7层的套路        Dim fa As New Facade.LoginFacade        Dim table = fa.GroupQuery(egroupquery)        If table Is Nothing Then            MsgBox("该条件下无记录~")
            '设置datagridview控件的数据源            DataGridView1.DataSource = Nothing        Else
            '这里也是一个虚方法            Todgv(table)        End If    End Sub    ' 定义虚函数GetDBName,获取不同数据库的字段名     Protected Overridable Function GetDBName(ByVal control As String) As String        Return ""    End Function    ' 定义虚函数GetTable,获取不同数据库的表名        Protected Overridable Function GetTable() As String        Return ""    End Function    '定义一个虚函数,设置不同的显示标题 Protected Overridable Sub Todgv(ByVal table As DataTable)    End Sub
End Class
     其他的小功能这里就不一一写了,很简单,这里只把一些重要的思想方法分析一下~


【子窗体的实现】

       创建一个子窗体,为继承的窗体。

      【机房个人重构】组合查询--模板方法

 接下来选择要继承哪个窗体:

      【机房个人重构】组合查询--模板方法

之后就会出现一个一模一样的窗体。

在子窗体里怎么实现继承呢?那就是重写方法,来实现个性化

     

Public Class frmStudentInfo
    '重写方法——在datagridview里面显示不同的标题    Protected Overrides Sub Todgv(table As DataTable)
        '从DAL层返回的table来赋给datagridview的数据源        DataGridView1.DataSource = table            DataGridView1.Columns(0).HeaderCell.Value = "卡号"               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 = "余额"        DataGridView1.Columns(8).HeaderText = "注册日期"        DataGridView1.Columns(9).HeaderText = "操作员"        DataGridView1.Columns(10).HeaderText = "年级"        DataGridView1.Columns(11).HeaderText = "班级"        DataGridView1.Columns(12).HeaderText = "备注"        DataGridView1.Columns(12).Visible = False          End Sub
    '重写方法——将用户选择的不同的字段名称转换成数据库中的字段,返回父窗体进行交流    Protected Overrides Function GetDBName(control As String) As String        Select Case (control)            Case "卡号"                Return "Chr_CardID"            Case "类型"                Return "Chr_Type"            Case "姓名"                Return "Chr_Name"            Case "性别"                Return "Chr_Sex"            Case "系别"                Return "Chr_Department"            Case "注册日期"                Return "EnrollDate"            Case "操作员"                Return "Chr_Operator"            Case "与"                Return "and"            Case "或"                Return "or"                            Case Else                Return ""        End Select    End Function
    '重写方法——赋值给DAL层要查哪个表的名称,返回父窗体    Protected Overrides Function GetTable() As String        egroupquery.GetTable = "View_CS"        Return egroupquery.GetTable    End Function
    '界面上的个性化显示    Private Sub frmStudentInfo_Load(sender As Object, e As EventArgs) Handles MyBase.Load        cmbField1.Items.Add("卡号")        cmbField1.Items.Add("类型")        cmbField1.Items.Add("姓名")        cmbField1.Items.Add("性别")        cmbField1.Items.Add("系别")        'cmbField1.Items.Add("机器号")        cmbField1.Items.Add("注册日期")        cmbField1.Items.Add("操作员")        cmbField2.Items.Add("卡号")        cmbField2.Items.Add("类型")        cmbField2.Items.Add("姓名")        cmbField2.Items.Add("性别")        cmbField2.Items.Add("系别")        'cmbField2.Items.Add("机器号")        cmbField2.Items.Add("注册日期")        cmbField2.Items.Add("操作员")        cmbField3.Items.Add("卡号")        cmbField3.Items.Add("类型")        cmbField3.Items.Add("姓名")        cmbField3.Items.Add("性别")        cmbField3.Items.Add("系别")        'cmbField3.Items.Add("机器号")        cmbField3.Items.Add("注册日期")        cmbField3.Items.Add("操作员")        'cmbOperation1.Items.Add("<")        'cmbOperation1.Items.Add(">")        cmbOperation1.Items.Add("=")        cmbOperation1.Items.Add("<>")        'cmbOperation2.Items.Add("<")        'cmbOperation2.Items.Add(">")        cmbOperation2.Items.Add("=")        cmbOperation2.Items.Add("<>")        'cmbOperation3.Items.Add("<")        'cmbOperation3.Items.Add(">")        cmbOperation3.Items.Add("=")        cmbOperation3.Items.Add("<>")        cmbRelation1.Items.Add("与")        cmbRelation1.Items.Add("或")        cmbRelation2.Items.Add("与")        cmbRelation2.Items.Add("或")    End Sub


    子窗体的功能就是下面这样与父窗体进行交流的:


    第一个,GetTable()方法:

    Protected Overrides Function GetTable() As String
        egroupquery.GetTable = "View_CS"
        Return egroupquery.GetTable
    End Function

     不用传递参数,直接返回,所以括号里面没有东西,直接定义返回的类型string。

告诉父窗体,我在这个子窗体里面要用哪个数据库的表。


     第二个,GetDBName():

     

Protected Overrides Function GetDBName(control As String) As String
Select Case (control)
Case "卡号"
Return "Chr_CardID"
       
        需要从父窗体里取值再返回,取值直接定义一个control这样的参数,给他string类型,再定义返回的类型string.

                                让父窗体知道,用户选择什么字段,我应该传递什么样的数据库的字段名称。

      第三个,Todgv方法

      

 Protected Overrides Sub Todgv(table As DataTable)
     这里跟前两个也不同,就是只取出父窗体的table的值,不返回,所以就没有后面的as string 这样的字。

【存储过程】

   

USE [Charge]
GO
/****** Object: StoredProcedure [dbo].[PROC_GroupQuery] Script Date: 03/26/2016 13:44:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PROC_GroupQuery]
@cmbField1 varchar(20),
@cmbField2 varchar(20),
@cmbField3 varchar(20),
@cmbOperation1 varchar(20),
@cmbOperation2 varchar(20),
@cmbOperation3 varchar(20),
@txtContent1 varchar(20),
@txtContent2 varchar(20),
@txtContent3 varchar(20),
@tableName varchar(20),
@cmbRelation1 varchar(20),
@cmbRelation2 varchar(20)

as
declare @TempSql varchar(500)
begin
SET @TempSql='SELECT * FROM '+@tableName +' WHERE ' +@cmbField1 +@cmbOperation1+char(39) + @txtContent1 + char(39)

if @cmbRelation1 != ''
BEGIN
SET @TempSql=@TempSql+@cmbRelation1+CHAR(32)+@cmbField2 +@cmbOperation2+CHAR(39)+@txtContent2+CHAR(39)
if @cmbRelation2!= ''
BEGIN
SET @TempSql=@TempSql+@cmbRelation2+CHAR(32)+@cmbField3+@cmbOperation3+CHAR(39)+@txtContent3+CHAR(39)
END
END
EXECUTE(@TempSql)
END


【小结】

       在组合查询的模板方法的应用里,如何在父窗体里写虚方法,如何做子窗体里继承重写方法,实现用一个父窗体模板,来让子窗体实现自己的个性化表现,很实用的功能。