【机房重构】组合查询——模板方法
来源:互联网 发布:php self this区别 编辑:程序博客网 时间:2024/04/30 22:41
前言
我们在学习第一次vb版机房收费系统的时候,面对组合查询,面对三个差异很小的窗体,我们的解决办法就是ctrl+c,ctrl+v。若干个月之后,我们学习了设计模式相关知识,再去解决组合查询时,才发现设计模式如此具有趣味性,它可以让我们的学习变得更加高效。
主要内容
1.模板方法模式
大话设计模式中的实例是"考题抄错会做也白搭",其中大概意思是,如果很多内容类似,我们只需设置一个模板,让所有类似的内容使用这个模板,这时只需修改很少的部分。
官话“模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。”
这里需要注意的是,模板方法很重要的思想是子类继承父类,通过重写实现功能。
2.实现
(1)建立父窗体,添加代码
UI层
Public Class frmGroupCheck '定义一个变量,用于接收文本框或者时间控件传递的内容 Public txt1 As String = "" Public txt2 As String = "" Public txt3 As String = "" '定义实体 Protected groupcheck As New Entity.GroupCheckEntity '窗体加载 Private Sub frmGroupCheck_Load(sender As Object, e As EventArgs) Handles MyBase.Load '操作符 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("<>") '关系 cmbRelations1.Items.Add("与") cmbRelations1.Items.Add("或") cmbRelations2.Items.Add("与") cmbRelations2.Items.Add("或") 'DateTimePicker控件的可见性 dtp1.Visible = False dtp2.Visible = False dtp3.Visible = False '在加载的时候,只有第一行控件可用,后两行控件不可用 cmbField2.Enabled = False cmbField3.Enabled = False cmbOperator2.Enabled = False cmbOperator3.Enabled = False cmbRelations2.Enabled = False txtContent2.Enabled = False txtContent3.Enabled = False '当选中dgvGroupCheck控件就选中行 dgvGroupCheck.SelectionMode = DataGridViewSelectionMode.FullRowSelect Dim i As Integer For i = 0 To dgvGroupCheck.Columns.Count - 1 dgvGroupCheck.Columns(i).Width = DataGridViewAutoSizeColumnMode.AllCells Next End Sub '清空 Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click cmbField1.Text = "" cmbField2.Text = "" cmbField3.Text = "" cmbOperator1.Text = "" cmbOperator2.Text = "" cmbOperator3.Text = "" txtContent1.Text = "" txtContent2.Text = "" txtContent3.Text = "" cmbRelations1.Text = "" cmbRelations2.Text = "" dgvGroupCheck.DataSource = "" End Sub '退出 Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click Me.Close() End Sub '查询 Private Sub btnInquiry_Click(sender As Object, e As EventArgs) Handles btnInquiry.Click '判断组合框不为空 If cmbRelations1.Text = "" Then '如果第一个组合关系框为空 If cmbField1.Text = "" Or cmbOperator1.Text = "" Or txt1 = "" Then MsgBox("第一行查询条件不能为空!", , "提示") Exit Sub End If End If If cmbRelations1.Text <> "" Then '如果选择了第一个组合关系 If cmbField2.Text = "" Or cmbOperator2.Text = "" Or txt2 = "" Then MsgBox("第二行查询条件不能为空!", , "提示") Exit Sub End If Else If cmbRelations2.Text <> "" Then '选择了第二个组合关系 If cmbField1.Text = "" Or cmbOperator1.Text = "" Or txt1 = "" Or cmbField2.Text = "" Or cmbField2.Text = "" Or txt2 = "" Or cmbField3.Text = "" Or cmbField3.Text = "" Or txt3 = "" Then MsgBox("第三行查询条件不能为空", , "提示") Exit Sub End If End If End If '给实体赋值 groupcheck.tableName = GetTable() groupcheck.cmbField1 = GetDBName(cmbField1.Text.Trim()) groupcheck.cmbField2 = GetDBName(cmbField2.Text.Trim()) groupcheck.cmbField3 = GetDBName(cmbField3.Text.Trim()) groupcheck.cmbOperator1 = cmbOperator1.Text.Trim() groupcheck.cmbOperator2 = cmbOperator2.Text.Trim() groupcheck.cmbOperator3 = cmbOperator3.Text.Trim() groupcheck.txtContent1 = txt1 groupcheck.txtContent2 = txt2 groupcheck.txtContent3 = txt3 groupcheck.cmbRelations1 = GetDBName(cmbRelations1.Text.Trim()) groupcheck.cmbRelations2 = GetDBName(cmbRelations2.Text.Trim()) '给外观层方法传递参数 Dim table As New DataTable Dim Fgroupcheck As New Facade.GroupCheckFacade table = Fgroupcheck.selectGroupCheck(groupcheck) If (table.Rows.Count = 0) Then MsgBox("没有符合条件的记录,请重新设置查询条件", , "提示") dgvGroupCheck.DataSource = Nothing Else Call Todatagridview() End If End Sub '当第一个组合关系框的内容发生改变时,设置第二行查询框的状态(是否可用) Private Sub cmbRelations1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelations1.SelectedIndexChanged cmbField2.Enabled = True cmbOperator2.Enabled = True txtContent2.Enabled = True cmbRelations2.Enabled = True End Sub '当第二个组合关系框的内容发生改变时,设置第三行查询框的状态(是否可用) Private Sub cmbRelations2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelations2.SelectedIndexChanged cmbField3.Enabled = True cmbOperator3.Enabled = True txtContent3.Enabled = True End Sub '定义虚函数GetDBName,获取不同数据库的字段名 Public Overridable Function GetDBName(ByVal control As String) As String Return "" End Function '定义虚函数GetTable,获取不同数据库的表名 Protected Overridable Function GetTable() As String Return "" End Function '把表显示到dgvGroupCheck中 Protected Overridable Sub Todatagridview() dgvGroupCheck.AutoSizeColumnsMode = DataGridViewAutoSizeColumnMode.AllCells End Sub '针对查询与日期、时间有关的问题 Private Sub cmbField1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbField1.SelectedIndexChanged If cmbField1.Text = "上机日期" Or cmbField1.Text = "下机日期" Or cmbField1.Text = "上机时间" Or cmbField1.Text = "下机时间" Then dtp1.Format = DateTimePickerFormat.Custom dtp1.Visible = True txtContent1.Visible = False If cmbField1.Text = "上机日期" Or cmbField1.Text = "下机日期" Then txt1 = Format(dtp1.Value, "yyyy-MM-dd") ElseIf cmbField1.Text = "上机时间" Or cmbField1.Text = "下机时间" Then dtp1.Format = DateTimePickerFormat.Time txt1 = Format(dtp1.Value, "hh:mm:ss") End If Else txt1 = txtContent1.Text End If End Sub '针对查询与日期、时间有关的问题 Private Sub cmbField2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbField2.SelectedIndexChanged If cmbField2.Text = "上机日期" Or cmbField2.Text = "下机日期" Or cmbField2.Text = "上机时间" Or cmbField2.Text = "下机时间" Then dtp2.Format = DateTimePickerFormat.Custom dtp2.Visible = True txtContent2.Visible = False If cmbField2.Text = "上机日期" Or cmbField2.Text = "下机日期" Then txt2 = Format(dtp2.Value, "yyyy-MM-dd") ElseIf cmbField2.Text = "上机时间" Or cmbField2.Text = "下机时间" Then dtp2.Format = DateTimePickerFormat.Time txt2 = Format(dtp2.Value, "hh:mm:ss") End If Else txt2 = txtContent2.Text End If End Sub '针对查询与日期、时间有关的问题 Private Sub cmbField3_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbField3.SelectedIndexChanged If cmbField3.Text = "上机日期" Or cmbField3.Text = "下机日期" Or cmbField3.Text = "上机时间" Or cmbField3.Text = "下机时间" Then dtp3.Format = DateTimePickerFormat.Custom dtp3.Visible = True txtContent3.Visible = False If cmbField3.Text = "上机日期" Or cmbField3.Text = "下机日期" Then txt3 = Format(dtp3.Value, "yyyy-MM-dd") ElseIf cmbField3.Text = "上机时间" Or cmbField3.Text = "下机时间" Then dtp3.Format = DateTimePickerFormat.Time txt3 = Format(dtp3.Value, "hh:mm:ss") End If Else txt3 = txtContent3.Text End If End SubEnd Class
Facade层
Public Function selectGroupCheck(GroupCheck As Entity.GroupCheckEntity) As DataTable Dim GroupCheckBLL As New BLL.GroupCheckBLL Dim table As New DataTable table = GroupCheckBLL.selectGroupCheck(GroupCheck) Return tableEnd FunctionB层
Public Function selectGroupCheck(ByVal GroupCheck As Entity.GroupCheckEntity) As DataTable Dim Factory As New Factory.Fac Dim IGroupCheck As IDAL.IGroupCheckDAL = Factory.GroupCheck Dim table As New DataTable table = IGroupCheck.selectGroupCheck(GroupCheck) If table.Rows.Count = 0 Then Return Nothing Else Return table End IfEnd FunctionD层
Imports System.Data.SqlClientPublic Class GroupCheckDAL : Implements IDAL.IGroupCheckDAL Private SqlHelper As SQLHelper.sqlhelper = New SQLHelper.sqlhelper() Public Function selectGroupCheck(ByVal GroupCheck As Entity.GroupCheckEntity) As DataTable Implements IDAL.IGroupCheckDAL.selectGroupCheck Dim sql As String = "PROC_GroupCheck" '调用存储过程 Dim table As DataTable Dim sqlparams As SqlParameter() = {New SqlParameter("@cmbField1", GroupCheck.cmbField1), New SqlParameter("@cmbField2", GroupCheck.cmbField2), New SqlParameter("@cmbField3", GroupCheck.cmbField3), New SqlParameter("@cmbOperator1", GroupCheck.cmbOperator1), New SqlParameter("@cmbOperator2", GroupCheck.cmbOperator2), New SqlParameter("@cmbOperator3", GroupCheck.cmbOperator3), New SqlParameter("@txtContent1", GroupCheck.txtContent1), New SqlParameter("@txtContent2", GroupCheck.txtContent2), New SqlParameter("@txtContent3", GroupCheck.txtContent3), New SqlParameter("@cmbRelations1", GroupCheck.cmbRelations1), New SqlParameter("@cmbRelations2", GroupCheck.cmbRelations2), New SqlParameter("@tableName", GroupCheck.tableName)} '设置参数 table = SqlHelper.GetDataTable(sql, CommandType.StoredProcedure, sqlparams) Return tableEnd FunctionEntity层
Private _cmbField1 As String Private _cmbField2 As String Private _cmbField3 As String Private _cmbOperator1 As String Private _cmbOperator2 As String Private _cmbOperator3 As String Private _txtContent1 As String Private _txtContent2 As String Private _txtContent3 As String Private _cmbRelations1 As String Private _cmbRelations2 As String Private _tableName As String
存储过程
USE [charge]GO/****** Object: StoredProcedure [dbo].[PROC_GroupCheck] Script Date: 04/28/2017 17:27:40 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGO-- ============================================= -- Author: 李佳丽-- Create date: 2017-4-19 -- Description: 用于组合查询时和数据库交互 -- ============================================= ALTER PROCEDURE [dbo].[PROC_GroupCheck] @cmbField1 varchar(20), @cmbOperator1 varchar(20), @txtContent1 varchar(20), @cmbField2 varchar(20), @cmbOperator2 varchar(20), @txtContent2 varchar(20), @cmbField3 varchar(20), @cmbOperator3 varchar(20), @txtContent3 varchar(20), @cmbRelations1 varchar(20), @cmbRelations2 varchar(20), @tableName varchar(20) AS declare @TempSql varchar(500) BEGIN SET @TempSql='SELECT * FROM '+@tableName +' WHERE ' +@cmbField1 +@cmbOperator1+char(39) + @txtContent1 + char(39) if (@cmbRelations1!='') BEGIN SET @TempSql=@TempSql+@cmbRelations1+CHAR(32)+@cmbField2 +@cmbOperator2+CHAR(39)+@txtContent2+CHAR(39) if (@cmbRelations2!='') BEGIN SET @TempSql=@TempSql+@cmbRelations2+CHAR(32)+@cmbField3+@cmbOperator3+CHAR(39)+@txtContent3+CHAR(39) END END EXECUTE(@TempSql) END
(2)建立子窗体,添加代码
右击命名空间(例如UI)-添加-类-已安装-常用项-Windows Forms-继承的窗体-选择继承的父类窗体
UI层代码
Public Class frmOpWorkRecord '单例模式 Private Shared frmOpWorkRecord As New frmOpWorkRecord Private Sub New() ' 此调用是设计器所必需的。 InitializeComponent() ' 在 InitializeComponent() 调用之后添加任何初始化。 End Sub Public Shared Function Getinstance() As frmOpWorkRecord If frmOpWorkRecord Is Nothing OrElse frmOpWorkRecord.IsDisposed Then frmOpWorkRecord = New frmOpWorkRecord frmOpWorkRecord.MdiParent = frmMain End If Return frmOpWorkRecord End Function '重写转换成数据库字段的方法 Public Overrides Function GetDBName(control As String) As String Select Case (control) Case "教师" Return "UserID" Case "级别" Return "Level" Case "上机日期" Return "LoginDate" Case "上机时间" Return "LoginTime" Case "下机日期" Return "LogoutDate" Case "下机时间" Return "LogoutTime" Case "机器名" Return "Computer" Case "状态" Return "Online" Case "与" Return "and" Case "或" Return "or" Case Else Return "" End Select End Function '重获表名的方法 Protected Overrides Function GetTable() As String groupcheck.tableName = "WorkLog_Info" Return groupcheck.tableName End Function '窗体加载 Private Sub frmOpWorkRecord_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 '重写方法 Protected Overrides Sub Todatagridview() Dim table As New DataTable Dim frmGroupCheck As New frmGroupCheck Dim FacadeGroupCheck As New Facade.GroupCheckFacade Try table = FacadeGroupCheck.selectGroupCheck(groupcheck) If table.Rows.Count = 0 Then table.Clear() dgvGroupCheck.DataSource = Nothing dgvGroupCheck.Refresh() MsgBox("记录为空") Else dgvGroupCheck.DataSource = table dgvGroupCheck.Columns(0).HeaderText = "用户名" dgvGroupCheck.Columns(1).HeaderText = "级别" dgvGroupCheck.Columns(2).HeaderText = "上机日期" dgvGroupCheck.Columns(3).HeaderText = "上机时间" dgvGroupCheck.Columns(4).HeaderText = "下机日期" dgvGroupCheck.Columns(5).HeaderText = "下机时间" dgvGroupCheck.Columns(5).HeaderText = "机器名" dgvGroupCheck.Columns(5).HeaderText = "状态" End If Catch ex As Exception MsgBox(ex.Message, vbOKOnly, "提示") End Try End SubEnd Class
3.遇到的问题
(1)@cmbRelations1!='' vs @cmbRelations1 is not null(存储过程中)
这个问题的关注点就在于“”与null的区别,可以查看一下数据库默认添加的值是空还是null。
(2)日期怎么传参?
当我们查询的内容是字符串类型时,直接将text值作为参数传递就可以。当我们查询的内容为日期(时间)时,需要将DateTimePicker的值作为参数传递,由于两个控件只可能传递一个参数,所以我们可以设一个变量去接收参数。
(3)子窗体的控件可以被编辑吗?
当子窗体继承父窗体的控件时,控件左上角会有个小锁的图标,此时的子窗体不能再修改自己的属性,原来问题出在父窗体控件的属性(Modifiers),此时只需将属性值改为“Protected”,即可在子窗体上重新编辑控件。
(4)D层可以用泛型吗?
第一次使用模板方法的时候,D层我使用的是泛型,结果就是可以查到记录的行数,却无法显示,标头显示的是实体名。
那么D层可以用泛型吗?答案是可以,由于三个子窗体同时继承一个父窗体,因此需要有三个实体集供一个方法转换,此时datatable转泛型需要重写三次。
小结
问题越多,收获越多。
- 【机房重构】——模板方法解决组合查询
- 【机房重构】组合查询——模板方法
- 机房重构—组合查询&模板方法
- 【机房重构】模板方法模式应用—组合查询
- 机房重构——组合查询(模板应用)
- 机房重构(5)——模板方法实现组合查询
- 组合查询=实体+模板方法——机房重构点滴积累
- 【机房重构】—模板方法+存储过程简单实现组合查询
- 机房重构组合查询模板方法再思考
- 【机房个人重构】组合查询--模板方法
- 【机房重构】组合查询之模板方法
- 机房重构——组合查询
- 机房重构——组合查询
- 机房重构——组合查询
- 机房重构——组合查询
- 机房重构—组合查询
- VB.NET版机房重构----模板方法+存储过程实现组合查询
- 机房重构组合查询之模板模式
- 在Windows下编译扩展OpenCV 3.1.0 + opencv_contrib
- Android开发集成微信分享
- [Python]面向对象编程---类、实例、方法的对比(4)
- hibernate获取session的两种方式分别是openSession() 方法和getCurrentSession() 方法。
- Construct Binary Tree from Preorder and Inorder Traversal 解题报告
- 【机房重构】组合查询——模板方法
- android google官方的下拉刷新SwipeRefreshLayout
- 日处理20亿数据,实时用户行为服务系统架构实践
- java 多态
- PCB布线中的地线干扰分析与抑制方法
- 【Java Utility】Jsoup网页爬虫工具简介Java HTML PARSER【一】
- win系统下清除MYSQL服务的命令
- 《JAVA设计模式》之简单工厂模式
- 如何在codewarrior中的flashprogrammer添加新的flash型号