首页 > 代码库 > 机房重构组合查询模板方法再思考

机房重构组合查询模板方法再思考

组合查询,对于机房来说可以算是一个很是值得我们认真考虑的地方,因为解决它的方法有很多种,但是想要找到一个最合适的却需要投入我们更多的思考。当然,不仅仅包括组合查询的SQL语句的组织,也包括检查它的完整性和对它进行数据库中的对应的字段的一个转换等问题。

学完设计模式后,大家在重构中大部分都应用了模板方法模式,这个模式在很大程度上减轻了组合查询中涉及到的代码重复问题。具体实现请见:http://blog.csdn.net/u010926964/article/details/37958153,在这篇博客中已经很好的解释了组合查询中模板方法的使用,在这里就不再重复。主要思路是建立一个空的窗体作为父窗体,而其余有具体执行内容的窗体作为子窗体,这样我们在编码过程中只需要对子窗体中不同执行过程的方法进行重写就可以了。

认真读过其中的代码后,发现存在的问题:

一、太多的if.....else语句,给人一种很不舒服的感觉,下面只是截取了一部分。

我们想一下,如果再加几条条件的话,我们也这样写吗?当然不是,是可以有解决办法的。看一下下面这张组合查询的条件界面:


简单的解释一下:这里我们仅让第一行控件和第一个组合框可用,当第一个组合框中有选择具体内容时,则第二行控件可用,否则不可用,第三行控件依次原理决定于第一个组合框。

那么在判断输入完整性的时候,可以根据组合框来判断:

‘当第一个组合框的内容发生改变时对是否可用进行判断:

 Private Sub cboCombination1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboCombination1.SelectedIndexChanged
        '对控件选择进行限定
        Dim relation As String = cboCombination1.Text.Trim
        Select Case relation
            Case "<请选择>"  '如果为空
                cboFeild2.Enabled = False
                cboOperater2.Enabled = False
                txtContent2.Enabled = False
                Exit Select
            Case Is <> "<请选择>"
                cboFeild2.Enabled = True
                cboOperater2.Enabled = True
                txtContent2.Enabled = True
                cboCombination2.Enabled = True
                Exit Select
        End Select
    End Sub
那么,第二个组合框发生改变时,与第一个类似,这样,我们将所有的这些控件放在了一个groupbox中,在点击查询时,只需要对所有可用的控件进行一个遍历即可,这样便省去了过多的if....else语句了。

如下:

’click查询事件中的一个遍历

'检查输入完整性
        Dim c As New Control
        For Each c In GroupBox1.Controls
            If c.Enabled = True Then
                If c.Text = "" Then
                    MsgBox("请填写完整您要查询的条件和内容!")
                    Exit Sub
                End If
            End If
        Next

经过上面这样几行代码就可以轻松的替代了长长的if....else语句给人带来的不快!


二、如何加载字段名并转换

大家还看链接中的那篇博客,会发现,当窗体加载时,会在combox中加载所选条件的名称,这篇博客中选择了一个个加载,显然感觉很冗余:如图


同时,在加载完汉语名称之后,还必须用一个长长的select case语句来进行与数据中具体的英文名称进行转换,这样又会出现大量的case,感觉还是不是很好的现象。

那么如何才能避免这种现象发生呢?

从大家的博客上学来的使用哈希表:

首先使用数组和循环加载字段名

 Dim fieldName() As String
        Dim DBName() As String
        '实例化一个哈希表

        fieldName = {"卡号", "登录日期", "登录时间", "下机日期", "下机时间", "消费金额", "<请选择>"}
        DBName = {"cardID", "loginDate", "loginTime", "offDate", "offTime", "consumeCash", ""} ’对应数据库中的字段名

在窗体加载时,直接按照指定的进行加载即可。

 '加载字段名
        cboFeild1.Items.AddRange(fieldName)
        cboFeild2.Items.AddRange(fieldName)
        cboFeild3.Items.AddRange(fieldName)

那么在点击查询时,如何让他与数据库中的字段对应起来呢?这里就用到了哈希表(Hashnable)

当然首先必须进行实例化然后:

  '当选择下拉框中的内容时,要对应数据库中的名字
        '定义字段名
        Dim DBFieldName1 As String
        Dim DBFieldName2 As String
        Dim DBFieldName3 As String

        '显示数据库名
        DBFieldName1 = hashtable.Item(cboFeild1.Text.Trim)
        DBFieldName2 = hashtable.Item(cboFeild2.Text.Trim)
        DBFieldName3 = hashtable.Item(cboFeild3.Text.Trim)

那么经过这样后,我们在执行SQL查询语句时,参数化查询过程中,我们将DBFieldName1,2,3直接赋给我们之前定义好的查询实体中的具体参数即可。

三、当list代替datatable时如何利用模板方法?

为什么这样说呢?难道不一样吗?可能是现在我们队集合的有关知识掌握的太有限,通常我们将datatable直接转换成一个具体实体类的list。那么仅仅如此,当我们使用它时,在D层,虽然我们所有的组合查询都只用了一个存储过程来完成,但是D层在返回类型时,每个方法只会返回一个实体类的list,这样随之到B层,也是同样如此。那么到U层结果就可想而知了,由于U层中要定义返回不同的实体类的list,所以,模板方法在这里似乎不能用。

但经过思考,在有限知识水平上,我们可以选择在外观层利用参数中表的不同,利用一个select语句来判断具体的要调用B层的哪个类,而在U层却只需要调用外观层中的这一个方法就好。这样就可以继续利用模板方法来做了。

可是问题又来了,我没有加外观层,那怎么办呢?其实代码都是活的,怎么改都还只是它本身的原理,我们可以在B层抽象出一个类,利用简单工厂来决定具体调用D层的那个方法。这样也可以利用模板方法了。

好了,通过以上的分析,模板方法最终还是用上了,不管用的还坏吧,这个阶段尽量还是用就好!