组合查询——怎样使用窗口的继承达到事半功倍?

一个优秀的程序猿就是要尽可能降低自己的代码量。我们日常的工作或者学习中都有可能遇到多个窗口结构类似,或者大同小异的情况,这时候假设在每一个窗口都写一遍代码,或者纯粹的复制粘贴就太水了。想要偷懒的时候正是我们发现和创造的机会,我们的祖先也是这么过来的。

我在做机房收费系统个人重构版的时候,就遇到了基本数据维护、查看上机状态、上机信息统计和操作员工作记录四个窗口都组要用到组合查询并且窗口结构一致。

四个窗口中除了字段名不一致,其它的内容都一样,这样的情况下我们用窗口的继承最合适了。在父窗口中写好公共的部分,不一致的地方能够写一个虚方法,然后让子类重写父类的虚方法。这样我们仅仅须要一个U层,一个B层,一个接口,一个抽象工厂,一个D层然后子类重写虚方法就能够实现四个窗口各自的功能了。

U层主要推断一下控件是否为空,给实体參数和B层方法传值传值,以及定义转换数据库字段的虚方法和获取表名的虚方法,这些虚方法在不同的子类中被重写以实现不同功能。

'*************************************************
'作者:邵鸿鑫
'小组:
'说明:组合查询模板
'创建日期:2014.7.9
'版本:
'**********************************************/
Public Class frmGroupQuery
    Public thisgroupquery As New Entity.GroupQueryEnpty '定义一个实体參数
    Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles btnQuery.Click

        '第一行组合关系为空
        If cmbRelation1.Text = "" Then
            '推断第一行控件内容是否为空
            If cmbField1.Text = "" Then
                MsgBox("请输入字段名")

            ElseIf cmbOperation1.Text = "" Then
                MsgBox("请输入操作符")

            ElseIf txtContent1.Text = "" Then
                MsgBox("请输入要查询的内容")

            End If
        End If

        ' 当第一个组合关系不为空时
        If cmbRelation1.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("请输入要查询的内容")
            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

        '给实体层传參
        Dim thisgroupquery As New Entity.GroupQueryEnpty
        thisgroupquery.cmbField1_text = GetDBName(cmbField1.Text.Trim())
        thisgroupquery.cmbField2_text = GetDBName(cmbField2.Text.Trim())
        thisgroupquery.cmbField3_text = GetDBName(cmbField3.Text.Trim())
        thisgroupquery.cmbOperation1_text = cmbOperation1.Text.Trim()
        thisgroupquery.cmbOperation2_text = cmbOperation2.Text.Trim()
        thisgroupquery.cmbOperation3_text = cmbOperation3.Text.Trim()
        thisgroupquery.txtContent1_text = txtContent1.Text.Trim()
        thisgroupquery.txtContent2_text = txtContent2.Text.Trim()
        thisgroupquery.txtContent3_text = txtContent3.Text.Trim()
        thisgroupquery.cmbRelation1_text = GetDBName(cmbRelation1.Text.Trim())
        thisgroupquery.cmbRelation2_text = GetDBName(cmbRelation2.Text.Trim())
        thisgroupquery.GetTable = GetTable()

        '给B层GroupQuery方法传递參数
        Dim db As New BLL.GroupQueryBLL
        If db.GroupQuery(thisgroupquery) Is Nothing Then
            MsgBox("没有记录,请又一次设置查询条件", vbOKOnly, vbExclamation)
            DataGridView1.DataSource = Nothing
        Else
            DataGridView1.DataSource = db.GroupQuery(thisgroupquery)
        End If
    End Sub

    ' 定义虚函数GetDBName,获取不同数据库的字段名
    Protected Overridable Function GetDBName(ByVal control As String) As String
        Return ""
    End Function

    ' 定义虚函数GetDBName,获取不同数据库的表名
    Protected Overridable Function GetTable() As String
        Return ""
    End Function
    Private Sub Button2_Click_1(sender As Object, e As EventArgs) Handles btnExit.Click
        Me.Hide()
    End Sub

    '组合关系一不为空后,显示第二行查询条件
    Private Sub cmbRelation1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelation1.SelectedIndexChanged
        cmbField2.Enabled = True
        cmbOperation2.Enabled = True
        cmbRelation2.Enabled = True
        txtContent2.Enabled = True
    End Sub

    '组合关系二不为空后,显示第三行查询条件
    Private Sub cmbRelation2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelation2.SelectedIndexChanged
        cmbField3.Enabled = True
        cmbOperation3.Enabled = True
        txtContent3.Enabled = True
    End Sub
End Class

B层写法跟曾经分层写法一样,引用工厂和接口返回查询到的表。

<span style="font-family:KaiTi_GB2312;font-size:18px;">'*************************************************
'作者:邵鸿鑫
'小组:
'说明:组合查询B层
'创建日期:2014.7.17
'版本:
'**********************************************/
Imports IDAL
Imports Entity
Public Class GroupQueryBLL
    Public Function GroupQuery(ByVal queries As Entity.GroupQueryEnpty) As DataTable
        Dim factory As New Factory.GroupQueryFactory
        Dim igroupquery As IGroupQuery = factory.GroupQuery
        Dim table = igroupquery.GroupQuery(queries)

        '检查D层返回的数据表中是否有数据
        If table.Rows.Count = 0 Then
            Return Nothing
        Else
            Return table
        End If
    End Function
End Class</span>

D层实现接口,调用存储过程实现对数据库的訪问。

<span style="font-family:KaiTi_GB2312;font-size:18px;">'*************************************************
'作者:邵鸿鑫
'小组:
'说明:组合查询D层
'创建日期:2014.7.17
'版本:
'**********************************************/
Imports System.Data.SqlClient
Imports IDAL
Public Class SqlserverGroupQueryDAL : Implements IGroupQuery
    Function GroupQuery(ByVal queries As Entity.GroupQueryEnpty) As DataTable Implements IGroupQuery.GroupQuery
        Dim strSQL As String = "PROC_GroupQuery" '调用存储过程
        Dim prams As SqlParameter() = {New SqlParameter("@cmbField1", queries.cmbField1_text),
                                    New SqlParameter("@cmbField2", queries.cmbField2_text),
                                    New SqlParameter("@cmbField3", queries.cmbField3_text),
                                    New SqlParameter("@cmbOperation1", queries.cmbOperation1_text),
                                    New SqlParameter("@cmbOperation2", queries.cmbOperation2_text),
                                    New SqlParameter("@cmbOperation3", queries.cmbOperation3_text),
                                    New SqlParameter("@txtContent1", queries.txtContent1_text),
                                    New SqlParameter("@txtContent2", queries.txtContent2_text),
                                    New SqlParameter("@txtContent3", queries.txtContent3_text),
                                    New SqlParameter("@cmbRelation1", queries.cmbRelation1_text),
                                    New SqlParameter("@cmbRelation2", queries.cmbRelation2_text),
                                    New SqlParameter("@tableName", queries.GetTable)} '设置參数
        Dim helper As New SqlHelper
        Dim table As New DataTable
        table = helper.GetDataTable(strSQL, CommandType.StoredProcedure, prams)
        Return table
    End Function
End Class</span>

存储过程

<span style="font-family:KaiTi_GB2312;font-size:18px;">-- =============================================
-- Author:		邵鸿鑫
-- Create date: 20140719
-- Description:	组合查询
-- =============================================
ALTER PROCEDURE [dbo].[PROC_GroupQuery]
	-- Add the parameters for the stored procedure here

	@cmbField1 varchar(10),
	@cmbOperation1 varchar(10),
	@txtContent1 varchar(10),
	@cmbField2 varchar(10),
	@cmbOperation2 varchar(10),
	@txtContent2 varchar(10),
	@cmbField3 varchar(10),
	@cmbOperation3 varchar(10),
	@txtContent3 varchar(10),
	@cmbRelation1 varchar(10),
	@cmbRelation2 varchar(10),
	@tableName varchar(20)
AS
	declare @TempSql varchar(500)--暂时存放sql语句
BEGIN
	SET @TempSql='SELECT * FROM '[email protected] +' WHERE ' [email protected] [email protected]+char(39) + @txtContent1 + char(39)
    if @cmbRelation1 != ''
    BEGIN
        SET @[email protected][email protected]+CHAR(32)[email protected] [email protected]+CHAR(39)[email protected]+CHAR(39)
        if @cmbRelation2!= ''
        BEGIN
        SET @[email protected][email protected]+CHAR(32)[email protected][email protected]+CHAR(39)[email protected]+CHAR(39)
        END
    END
EXECUTE(@TempSql)
END</span>

抽象工厂应用配置文件,实现灵活更换数据库。

<span style="font-family:KaiTi_GB2312;font-size:18px;">'*************************************************
'作者:邵鸿鑫
'小组:
'说明:组合查询抽象工厂
'创建日期:2014.7.17
'版本:
'**********************************************/
Imports System.Reflection
Imports System.Configuration
Imports IDAL
Public Class GroupQueryFactory
    Private Shared ReadOnly AssemblyName As String = "DAL" '声明程序集名称
    Private Shared ReadOnly db As String = ConfigurationManager.AppSettings("DB") '读取配置文件到db
    Public Function GroupQuery() As IGroupQuery
        Dim className As String = AssemblyName + "." + db + "GroupQueryDAL"
        Dim igroupquery As IGroupQuery
        igroupquery = CType(Assembly.Load(AssemblyName).CreateInstance(className), IGroupQuery)
        Return igroupquery
    End Function
End Class
</span>

子类代码以操作员工作记录为例,首先加入继承窗口

然后选择被继承的窗口

之后就是重写父类的虚方法

<span style="font-family:KaiTi_GB2312;font-size:18px;">'*************************************************
'作者:邵鸿鑫
'小组:
'说明:查询操作员工作记录U层
'创建日期:2014.7.18
'版本:
'**********************************************/
Public Class frmworklog

    '重写转换成数据库字段方法
    Protected Overrides Function GetDBName(ByVal control As String) As String
        Select Case (control)
            Case "教师"
                Return "userName"
            Case "上班日期"
                Return "loginTime"
            Case "上班时间"
                Return "loginTime"
            Case "下班日期"
                Return "offTime"
            Case "下班时间"
                Return "offTime"
            Case "机器号"
                Return "computer"
            Case "与"
                Return "and"
            Case "或"
                Return "or"
            Case Else
                Return ""
        End Select
    End Function

    '重写获得表名方法
    Protected Overrides Function GetTable() As String
        thisgroupquery.GetTable = "Work_info"
        Return thisgroupquery.GetTable
    End Function

    Public Sub frmworklog_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("机器号")

        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("机器号")
    End Sub
End Class</span>

为了避免用户不按顺序组合查询条件,把第二行和第三行查询条件以及第二个组合关系设的属性置为不可用,仅仅有第一个组合关系不为空时第二行查询条件和第二个组合关系才干使用,同理第二个组合关系不为空时第三行组合条件才干使用。

言归正传这一切的一切都是为了降低我们的工作量,人类的进步事实上就是一次次为了“偷懒”而不断探索的过程。文章中有不足之处还请大神们批评指正,希望能对大家有所帮助。

时间: 2024-11-12 21:55:27

组合查询——怎样使用窗口的继承达到事半功倍?的相关文章

组合查询——如何使用窗体的继承达到事半功倍?

一个优秀的程序员就是要尽可能减少自己的代码量.我们日常的工作或者学习中都有可能遇到多个窗体结构类似,或者大同小异的情况,这时候如果在每个窗体都写一遍代码,或者纯粹的复制粘贴就太水了.想要偷懒的时候正是我们发现和创造的机会,我们的祖先也是这么过来的. 我在做机房收费系统个人重构版的时候,就遇到了基本数据维护.查看上机状态.上机信息统计和操作员工作记录四个窗体都组要用到组合查询而且窗体结构一致. 四个窗体中除了字段名不一致,其他的内容都一样,这种情况下我们用窗体的继承最合适了.在父窗体中写好公共的部

组合查询——继承与多态的小练习

上次个人版机房收费做的时候,组合查询这里做的不好,没有抽出模板,导致感觉有很多冗余,这次自己挑U层,一方面是感觉自己的B层和D层做的可以提升的空间目前很小了,另一方面就是想加强一下自己对细节的注意问题. 上次组合查询是这样的,以代码为例: U层代码如下: Imports System.Collections '引入HashTable类 Public Class frmColWorkInfo Dim HtZD As New Hashtable '定义处理字段名转换的hashtable Dim Ht

重构—组合查询

组合查询是重构中的一个重点,也是比较麻烦的,但是我们可以用一个很好的办法来解决它,比如窗体继承,模板方法.关于窗体继承请参考博文:http://blog.csdn.net/augus3344/article/details/29384877 讲的很详细.这里主要说下模板方法,用这个方法可以为我们省掉很多繁琐的步骤和重复的代码.我们就以父窗体为模板,继承窗体来实现不同的模板,也就是将公共的代码写到模板中,自己特有的代码写到自己的模块,下面看代码. 父窗体的代码 U层代码 ImportsSystem

VB.NET版机房收费系统---组合查询

查询的意思就是查找,寻找,指在某一个或几个地方找出自己所要的信息,假如我想搜索一下我自己写的博客,名字叫做初雪之恋,我在百度的搜索框中输入丁国华三个字,会有如何的惊喜等着我? 啊哦,这个信息并非我想要的,于是我再搜,"丁国华 廊坊师范学院  csdn"搜索结果例如以下: 非常显然,这个还不是我想要的结果,我接着搜,"丁国华 廊坊师范学院 csdn 初雪之恋": 在我的理解中,组合查询就是通过条件层层限制,一步一步精确,得到我们想要的答案,在机房收费系统中,有好几处涉

VB.NET+三层 机房收费系统之组合查询

关系组合查询已经用去了4天的时间.每天都在痛苦中煎熬,绞尽脑汁,一句代码都要瞪大眼睛看好长时间,有时候.由于两句话颠倒了.就nothing了:有时候,由于table如何可以转换成实体类型.将自己困住了.一想就是半天.状况不断呀.看了非常多师哥师姐们的代码,他们分享着自己的代码.为了给大家一点东西,给拿出自己给大家分享.期望大家能给点意见. 步骤: (1).首先建立实体,实体是用来存储变量的. (2).建立B层,B层除了有调用D层的函数,同一时候,它也有将汉字转换为sql中的字段的功能. (3).

机房重构---由组合查询引发的思考

前言: 不要基于代码编程,要基于图形进行软件设计. ---米老师 As mentionedabove,是上上个周四晚上锁门时候在小会议室听到米老师给九期师哥师姐讲系统时候的一句话,让我很是触动.Why? 有个问题不知道大家思考过没有,比如在<设计模式>学习过程中,我们照着代码"照葫芦画瓢"似的把代码敲了出来,貌似自己真的懂了,但是真正让自己去实践的时候,我们能做出来吗?或者在敲机房时候,有些难点我们是模仿"前人"博客做出来的,程序能跑起来了,代码自己也理

机房重构之模版方法模式-组合查询

机房收费系统中,一个比较让人纠结功能就是组合查询,不仅仅是代码比较多,而且大多都是重复的代码,也正是因为如此,才比较适合模版方法模式. 一.基本介绍 模版方式模式是定义一个操作中的算法的骨架,而将步骤延迟到子类中. 模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 类图 二.具体实现 1.建立模板父窗体 添加Windows窗体,设计模板界面(如下图),并在模板窗体里写入抽象出来的类和方法的代码. '**************************************

组合查询(机房重构知识点总结)

历经n多天,组合查询模板终于做完了,总结一下这几天的成果,和大家一起学习交流. 先看一下父窗体的关键代码: 父窗体代码: Public Class frmComboQuery Protected Overridable Sub frmComboQuery_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim ComboxArray(4) As ComboBox '定义控件数组,获取组合框 ComboxArray(0) = c

机房重构(5)——模板方法实现组合查询

在敲机房收费过程中,我们会发现很多窗体除了一些细微的差别外,基本是一模一样的,功能的实现也是大同小异.在第一次机房收费的时候,我们都是"好学生",尽管代码重复率极高,还是按部就班的一个个的实现.但在学习了设计模式,机房重构的现在,再傻傻的重复代码,就不是明智之举了. 整个收费系统中,总计有四个组合查询的功能(界面如图),为了提高代码复用率,提高效率,就引入了模板方法实现. 模板方法模式,定义了一个操作中的算法的骨架,把一些步骤延迟到子类当中.它使得子类可以不改变一个算法的结构即可重定义