【个人机房重构】—— 模版方法实现组合查询

来源:互联网 发布:mac如何截取整个网页 编辑:程序博客网 时间:2024/04/30 20:47

背景:在机房收费系统中,有好多基本上一样的窗体。比如:查看学生充值记录与学生上机记录、金额收取信息查询与金额退还信息查询,还有组合查询中:学生信息维护、操作员工作记录、学生上机信息统计。在这个时候,为了提高效率,我们应该怎样去做呢?


一、模版方法概述


模版方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

    有时,我们知道一个算法需要的步骤和顺序,但是每个算法的具体实现不同。比如在机房收费系统中,组合查询有三个窗体类,每个窗体类的算法结构相同,具体实现不同,此时我们可以使用模版方法。

    模版方法模式 把我们不知道具体实现的步骤封装成抽象方法,提供一个按正确顺序调用他们的具体方法,构成一个抽象基类,子类继承抽象基类实现各个步骤的抽象方法,工作流程由抽象基类控制。把实现推迟到子类中,通过继承来达到对象的复用,同时遵守了开闭原则。


二、实战演练


1、首先,我们需要建立一个模版窗体




2、然后需要建立子窗体进行继承(我们以“学生信息维护”为例)


①创建继承窗体




②选择要继承哪个窗体




这样,”学生信息维护“的组合查询就建好了。


3、实现代码


U层


'********************************************** ' 文 件 名:frmGroupQuery' 命名空间:UI' 内    容:' 功    能:组合查询的模版窗体' 文件关系:' 作    者:杨晨光' 小    组:' 生成日期:2014/8/25 14:14:37' 版 本 号:V1.0.0.0' 修改日志:' 版权说明:'**********************************************Public Class frmGroupQuery    '实例化一个新的实体对象,    Protected EGroup As New Entity.GroupQueryEntity    '窗体加载    Private Sub frmGroupQuery_Load(sender As Object, e As EventArgs) Handles MyBase.Load        '窗体加载时,给字段、操作符、组合关系赋值        '加载组合关系        cmbRelation1.Items.Add("并且")        cmbRelation2.Items.Add("并且")        cmbRelation1.Items.Add("或者")        cmbRelation2.Items.Add("或者")        '给操作符赋值        cmbOperator1.Items.Add("=")        cmbOperator1.Items.Add(">")        cmbOperator1.Items.Add("<")        cmbOperator1.Items.Add("<>")        cmbOperator2.Items.Add("=")        cmbOperator2.Items.Add(">")        cmbOperator2.Items.Add("<")        cmbOperator2.Items.Add("<>")        cmbOperator3.Items.Add("=")        cmbOperator3.Items.Add(">")        cmbOperator3.Items.Add("<")        cmbOperator3.Items.Add("<>")        '窗体加载后,后两行文本框不能使用        cmbFields2.Enabled = False        cmbOperator2.Enabled = False        txtContext2.Enabled = False        cmbFields3.Enabled = False        cmbOperator3.Enabled = False        txtContext3.Enabled = False    End Sub    '单击查询按钮    Private Sub btnCheck_Click(sender As Object, e As EventArgs) Handles btnCheck.Click        '先将DataGridView中清空        DataGridView.DataSource = Nothing        '判断文本框、组合框是否为空        '第一个组合关系为空时,第一行的都不能为空        If cmbRelation1.Text = "" Then            Dim arrayControl() As Control            ReDim Preserve arrayControl(2)            arrayControl(0) = cmbFields1            arrayControl(1) = cmbOperator1            arrayControl(2) = txtContext1            '调用模块,来进行判断是否为空            If IsEmpty.IsAllEmptyText(arrayControl) Then                Exit Sub            End If        End If        '第一个组合关系文本框不为空,则判断前两行不能为空        If cmbRelation1.Text <> "" Then            Dim arrayControl() As Control            ReDim Preserve arrayControl(5)            arrayControl(0) = cmbFields1            arrayControl(1) = cmbOperator1            arrayControl(2) = txtContext1            arrayControl(3) = cmbFields2            arrayControl(4) = cmbOperator2            arrayControl(5) = txtContext2            '调用模块,来进行判断是否为空            If IsEmpty.IsAllEmptyText(arrayControl) Then                Exit Sub            End If        End If        '第二个组合关系文本框不为空,判断所有的不为空        If cmbRelation2.Text <> "" Then            Dim arrayControl() As Control            ReDim Preserve arrayControl(8)            arrayControl(0) = cmbFields1            arrayControl(1) = cmbOperator1            arrayControl(2) = txtContext1            arrayControl(3) = cmbFields2            arrayControl(4) = cmbOperator2            arrayControl(5) = txtContext2            arrayControl(6) = cmbFields3            arrayControl(7) = cmbOperator3            arrayControl(8) = txtContext3            '调用模块,来进行判断是否为空            If IsEmpty.IsAllEmptyText(arrayControl) Then                Exit Sub            End If        End If        '给实体赋值(需要在实体层新建一个实体类)        EGroup.Fields1 = GetDBName(cmbFields1.Text.Trim())        EGroup.Fields2 = GetDBName(cmbFields2.Text.Trim())        EGroup.Fields3 = GetDBName(cmbFields3.Text.Trim())        EGroup.Operator1 = cmbOperator1.Text.Trim()        EGroup.Operator2 = cmbOperator2.Text.Trim()        EGroup.Operator3 = cmbOperator3.Text.Trim()        EGroup.Context1 = txtContext1.Text.Trim()        EGroup.Context2 = txtContext2.Text.Trim()        EGroup.Context3 = txtContext3.Text.Trim()        EGroup.Relation1 = GetDBName(cmbRelation1.Text.Trim())        EGroup.Relation2 = GetDBName(cmbRelation2.Text.Trim())        EGroup.GetList = GetList()        '调用B层的方法,进行传递参数        Dim BGroup As New BLL.GroupQueryBLL     '实例化B层的对象        Dim dt As New DataTable        Call Dview()    End Sub    '组合关系A文本框是否有值,会影响到下边行的能否操作的问题    Private Sub cmbRelation1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelation1.SelectedIndexChanged        '组合关系A中没有东西        If cmbRelation1.Text <> "" Then            cmbFields2.Enabled = True            cmbOperator2.Enabled = True            txtContext2.Enabled = True        End If    End Sub    '组合关系B文本框是否有值,会影响到下边行的能否操作的问题    Private Sub cmbRelation2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelation2.SelectedIndexChanged        '组合关系B中没有值        If cmbRelation2.Text <> "" Then            cmbFields3.Enabled = True            cmbOperator3.Enabled = True            txtContext3.Enabled = True        End If    End Sub    ' 定义虚函数GetDBName,获取不同数据库的字段名        Protected Overridable Function GetDBName(ByVal control As String) As String        Return ""    End Function    ' 定义虚函数GetList,获取不同数据库的表名        Protected Overridable Function GetList() As String        Return ""    End Function    '定义虚函数Dview,将数据显示到控件中    Protected Overridable Sub Dview()    End Sub    '导出到Excel表    Private Sub btnLead_Click(sender As Object, e As EventArgs) Handles btnLead.Click        Call ImportToExcel.ImportToExcel(DataGridView)    '调用的导出Excel表的模块    End SubEnd Class


B层


Public Class GroupQueryBLL    Function Query(ByVal user As Entity.GroupQueryEntity) As DataTable        Dim fty As New AbsFactory.DataAccess      '实例化一个新的工厂对象        Dim IGroup As IDAL.IGroupQuery            '定义一个接口函数        'Dim myList As List(Of Entity.GroupQueryEntity)    '定义一个泛型集合,用来承接返回值        Dim dt As DataTable        IGroup = fty.CreateIGroupQuery        dt = IGroup.Query(user)        Return dt    End FunctionEnd Class

工厂层


Public Class DataAccess    '通过配置文件获取连接字符串并赋值给所声明的变量strConnection    Dim strConnection As String = ConfigurationManager.AppSettings("DALName")    '组合查询表    Public Function CreateIGroupQuery() As IDAL.IGroupQuery        Return CType(Assembly.Load(strConnection).CreateInstance(strConnection + "." + "GroupQueryDAL"), IDAL.IGroupQuery)    End FunctionEnd Class

接口层


Public Interface IGroupQuery    '定义一个组合查询的接口函数,,,返回值为DataTable    Function Query(ByVal user As Entity.GroupQueryEntity) As DataTableEnd Interface

D层


Public Class GroupQueryDAL    : Implements IGroupQuery    '定义组合查询的函数    Public Function Query(user As Entity.GroupQueryEntity) As DataTable Implements IGroupQuery.Query        '定义一个数据库操作的助手类        Dim MySqlHelper As New SqlHelper        '定义一个数据库操作的语句        Dim strSql As String        '调用存储过程        strSql = "PROC_GroupQuery"        '加入参数        Dim paras As SqlParameter() = {New SqlParameter("@Fields1", user.Fields1),                                       New SqlParameter("@Fields2", user.Fields2),                                       New SqlParameter("@Fields3", user.Fields3),                                       New SqlParameter("@Operator1", user.Operator1),                                       New SqlParameter("@Operator2", user.Operator2),                                       New SqlParameter("@Operator3", user.Operator3),                                       New SqlParameter("@Context1", user.Context1),                                       New SqlParameter("@Context2", user.Context2),                                       New SqlParameter("@Context3", user.Context3),                                       New SqlParameter("@Relation1", user.Relation1),                                       New SqlParameter("@Relation2", user.Relation2),                                       New SqlParameter("@GetList", user.GetList)}        '定义一个dt,用来保存执行结果的值        Dim dt As DataTable        dt = MySqlHelper.ExecSelect(strSql, CommandType.StoredProcedure, paras)        Return dt    End FunctionEnd Class

存储过程


-- =============================================-- Author:杨晨光>-- Create date: <Create Date,,>-- Description:组合查询-- =============================================ALTER PROCEDURE [dbo].[PROC_GroupQuery]--加入参数@Fields1  varchar(10),@Fields2  varchar(10),@Fields3  varchar(10),@Operator1  varchar(10),@Operator2  varchar(10),@Operator3  varchar(10),@Context1  varchar(20),@Context2  varchar(20),@Context3  varchar(20),@Relation1  varchar(10),@Relation2  varchar(10),    @GetList  varchar(20)--获取表的名称    ASdeclare @TempSql varchar(500)--临时存放sql语句 BEGINSET @TempSql='SELECT * FROM '+@GetList +' WHERE ' +@Fields1 +@Operator1+char(39) + @Context1 + char(39)        if @Relation1 != ''--第一个组合关系文本框不为空BEGINSET @TempSql=@TempSql+@Relation1+CHAR(32)+@Fields2 +@Operator2+CHAR(39)+@Context2+CHAR(39)            if @Relation2 != ''--第二个组合关系文本框不为空        BEGIN            SET @TempSql=@TempSql+@Relation2 +CHAR(32)+@Fields3+@Operator3+CHAR(39)+@Context3+CHAR(39)            END   ENDEXECUTE(@TempSql)END

以上是父窗体的代码(实体层就不写了),下边是子类(学生信息维护)窗体的代码


Imports System.Collections     '引入哈希表Public Class frmSInfoMaintain    Private Sub frmSInfoMaintain_Load(sender As Object, e As EventArgs) Handles MyBase.Load        '表名        Me.Text = "学生基本信息维护"        Dim haField As New Hashtable    '定义处理字段名转换的hashtable        '使用哈希表叫数据库中的字段进行转换        Dim FieldName() As String        Dim FieldValue() As String        '数据库中的字段对应相应的中文        FieldName = {"卡号", "学号", "姓名", "性别", "系别", "年级", "班级"}        FieldValue = {"userNo", "studentID", "studentName", "Sex", "Department", "Grage", "Class"}        '放到Field字段中        cmbFields1.Items.AddRange(FieldName)        cmbFields2.Items.AddRange(FieldName)        cmbFields3.Items.AddRange(FieldName)        '中文为key,英文为value添加到hashtable          For i As Integer = 0 To FieldName.Count - 1            haField.Add(FieldName(i), FieldValue(i))        Next    End Sub    '重写获得表名方法      Protected Overrides Function GetList() As String        Return "T_StudentInfo"    End Function    '重写转换成数据库字段方法      Protected Overrides Function GetDBName(ByVal control As String) As String        Select Case (control)            Case "卡号"                Return "cardNo"            Case "学号"                Return "studentID"            Case "姓名"                Return "studentName"            Case "性别"                Return "Sex"            Case "系别"                Return "Department"            Case "年级"                Return "Grade"            Case "班级"                Return "Class"            Case "并且"                Return "and"            Case "或者"                Return "or"            Case Else                Return ""        End Select    End Function    Protected Overrides Sub Dview()        '每次数据查询,情况表        DataGridView.DataSource = Nothing        '表格控件绑定数据源字段        '调用B层的方法,进行传递参数        Dim BGroup As New BLL.GroupQueryBLL      '实例化B层的对象        Dim dt As New DataTable        dt = BGroup.Query(EGroup)        If dt.Rows.Count = 0 Then            MsgBox("没有记录,请重新进行查询!", MsgBoxStyle.Exclamation, "警告")            DataGridView.DataSource = Nothing        Else            DataGridView.DataSource = dt            DataGridView.DataSource = dt            DataGridView.Columns(0).HeaderText = "卡号"            DataGridView.Columns(1).HeaderText = "学号"            DataGridView.Columns(2).HeaderText = "姓名"            DataGridView.Columns(3).HeaderText = "性别"            DataGridView.Columns(4).HeaderText = "系别"            DataGridView.Columns(5).HeaderText = "年级"            DataGridView.Columns(6).HeaderText = "班级"            DataGridView.Columns(7).Visible = False            DataGridView.Columns(8).Visible = False            DataGridView.Columns(9).Visible = False            DataGridView.Columns(10).Visible = False            DataGridView.Columns(11).Visible = False            '删除最下边的一行            DataGridView.AllowUserToAddRows = False        End If    End SubEnd Class


三、反思


    使用模版方法实现组合查询虽然实现了,但是其中还是有一些不足。例如:层与层之间传递数据使用的DataTable,我曾经尝试使用泛型集合来进行传递,可是没能成功,所以最后只能妥协使用DataTable。在子窗体进行继承的时候,使用了哈希表,减少了部分代码。虽然使用了哈希表,但是对它的了解还是很模糊,还有待于去钻研。

            记住:多思考,多总结。








0 0
原创粉丝点击