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

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


【功能概况】

  【机房个人重构】组合查询--模板方法_第1张图片

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


【具体实现】

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

    【机房个人重构】组合查询--模板方法_第2张图片

     里面的代码如下:

   

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
     其他的小功能这里就不一一写了,很简单,这里只把一些重要的思想方法分析一下~


【子窗体的实现】

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

      【机房个人重构】组合查询--模板方法_第3张图片

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

      【机房个人重构】组合查询--模板方法_第4张图片

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

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

     

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
      
     

【小结】

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

          


你可能感兴趣的:(模板方法,组合查询,机房重构)