摘要使用面向对象编程工具处理数据库问题时,可以通过创建类模块把数据管理逻辑和用户接口逻辑独立开来,即把管理数据封装在类模块中。在应用程序有多个接口让用户编辑相同数据时,这种方法可以实现代码共享,当用户修改底层数据库时,其窗体的用户接口逻辑不用改变。本文介绍了创建数据管理逻辑和用户接口逻辑的基本方法,给出了一般化模型,并以VB6为例说明具体实现方法。
关键字类(Class) 窗体(Form)数据库(Database) 封装(encapsulation)
使用面向对象的编程工具进行数据库开发时,有很多工具可以使用,如VB、Delphi、PB、VFP等。它们的共同特点是可以通过创建类模块把数据管理逻辑和用户接口逻辑独立开来。在类模块中进行数据管理,如连接数据库、创建结果集、定义私有变量完成当前记录的中间存取等。在窗体中通过创建类实例就可以完成数据库连接,通过对类属性的操作实现类模块和窗体之间的数据传递,进而实现对结果集的操作,如记录的浏览、添加、删除等。由于在窗体的用户接口逻辑中不对具体的结果集进行操作,也不对具体的字段进行操作,其操作对象只是类属性,对结果集的操作全部封装在类模块中,这样就创建了数据库和用户接口之间的独立层。采用这种分离技术,可以创建许多不同的窗体,所有的窗体使用同一个类而不用复制任何数据管理逻辑,类模块中代码被多个窗体共享。另外,对底层数据库的修改只在类中进行,而不需要对基于它的窗体做任何改变。
不论使用那种编程工具,实现数据管理逻辑和用户接口逻辑分离的基本方法是一致的。本文给出一个一般化的处理模型,再以VB6为例,说明具体的实现方法。
一实现数据管理逻辑和用户接口逻辑分离的一般化处理模型
⑴在装载窗体时创建类实例。在类初始化中完成数据库连接、创建结果集、取当前记录到一组类私有变量中。
⑵在窗体中浏览记录时,通过调用类自定义方法,实现结果集中记录指针的移动。同时在类模块中取当前记录到一组私有变量中,为把数据传递给窗体做好准备。
⑶在类模块中,为每一个字段定义一个属性。读属性时,把相应私有变量值送属性。写属性时,把要写的内容送私有变量。
⑷在窗体中进行读操作时,只读相应属性,实质是读类私有变量,而私有变量中已存好了当前记录值。
⑸写操作时,只把当前值写到属性中,实质是写到类私有变量中,再通过类自定义方法写到结果集中。
其大致关系可用下图描述:
窗体
类模块
装载窗体
创建类实例
类实例初始化连接数据库、创建结果集
取当前记录到类私有变量
读数据
实质为读属性
当前记录已存放在类私有变
量中,读属性的实质即返回私有变量
写数据
实质为写属性
写属性实际是把控件值写到
类私有变量中,再调用类自
定义方法写到结果集中
用户接口逻辑 数据管理逻辑
二使用VB6处理上述问题的实际例子
⒈创建类Cstudent并做如下操作
⑴做下述定义:
Private cnnStudent As New ADODB.Connection
Private mStudent As New ADODB.Recordset
Private mstrName As String
Private mstrSex As String
Private mintAge As Integer
Public Enum CStudentMove
FirstRecord = 0
PreviousRecord = 1
NextRecord = 2
LastRecord = 3
End Enum
这里采用ADO,定义了三个私有变量mstrName、mstrSex、mintAge分别对应结果集中的Name、Sex、Age,枚举类型CstudentMove包含四个常量,为结果集指针移动做准备。
⑵在Cstudent的Class_Initialize()中添加如下代码:
Private Sub Class_Initialize()
‘创建并打开结果集
Dim StrSql As String
cnnStudent.Provider = "Microsoft.Jet.OLEDB.3.51"
cnnStudent.ConnectionString = "c:\access\student.mdb"
cnnStudent.Open
StrSql = "select * from sName"
mStudent.ActiveConnection = cnnStudent
mStudent.CursorType = adOpenKeyset
mStudent.LockType = adLockOptimistic
mStudent.Open StrSql
‘调用GetCurrentRecord方法,取结果集当前记录到私有变量
GetCurrentRecord
End Sub
⑶添加如下属性过程:
Public Property Get Name() As String
Name = mstrName
End Property
Public Property Let Name(ByVal vNewValue As String)
mstrName = vNewValue
End Property
Public Property Get Sex() As String
Sex = mstrSex
End Property
Public Property Let Sex(ByVal vNewValue As String)
mstrSex = vNewValue
End Property
Public Property Get Age() As String
Age = mstrAge
End Property
Public Property Let Age(ByVal vNewValue As String)
mstrAge = vNewValue
End Property
这六个属性分别对应字段Name、Sex、Age。读属性时执行Get过程,写属性时执行Let过程。
⑷在类模块中定义SaveRecord和GetCurrentRecord方法
Public Sub SaveRecord()
mStudent.Edit
mStudent.Fields("Name") = mstrName
mStudent.Fields("Sex") = mintSex
mStudent.Fields("Age") = mstrAge
mStudent.Update
End Sub
Public Sub GetCurrentRecord ()
mstrName = mStudent.Fields("Name").Value
mintAge = mStudent.Fields("Age").Value
mstrSex = mStudent.Fields("Sex").Value
End Sub
⑸在类模块中定义Move方法如下:
Public Sub Move(MoveType As Integer)
Select Case MoveType
Case 0
mStudent.MoveFirst
Case 1
mStudent.MovePrevious
Case 2
mStudent.MoveNext
Case 3
mStudent.MoveLast
End Select
GetCurrentRecord
End Sub
⑹在类的Class_Terminate()中添加如下代码:
Private Sub Class_Terminate()
mStudent.Close
Set mStudent = Nothing
cnnStudent.Close
Set cnnStudent = Nothing
End Sub
⒉在窗体中做如下操作
⑴在Form_Load()中添加如下代码
Private Sub Form_Load()
Set mclsStudent = New Cstudent ‘创建类实例
GetData
End Sub
⑵定义GetData方法
Private Sub GetData()
txt(0).Text = mclsStudent.Name‘读属性值到控件
txt(1).Text = mclsStudent.Sex ‘读属性值到控件
txt(2).Text = mclsStudent.Age ‘读属性值到控件
End Sub
⑶定义Command按钮的Click事件
Private Sub cmdMove_Click(Index As Integer)
mclsStudent.SaveRecord
Select Case Index
Case 0
mclsStudent.Move FirstRecord
Case 1
mclsStudent.Move PreviousRecord
Case 2
mclsStudent.Move NextRecord
Case 3
mclsStudent.Move LastRecord
End Select
GetData
End Sub
⑷在Form_UnLoad()中添加如下代码
Private Sub Form_UnLoad()
mclsStudent.SaveRecord
Unload Me
End Sub
为简化起见,这里的表sName只有三个字段Name、Sex、Age。
可以看出,所有的数据管理都在类模块中进行。在窗体中不直接对结果集和字段操作,操作对象是类属性和类方法。真正实现了数据管理逻辑和用户接口逻辑的分离,创造了它们之间的独立层,为程序的进一步开发奠定了基础。不难在此基础上增加记录添加、删除、撤消等功能。
在应用程序有多个接口让用户编辑相同数据时,这种方法的优越性将显示出来。它不仅可以使管理数据的大部分代码得到共享,简化了程序设计,而且程序的修改,特别是底层数据库的修改变得非常容易。真正发挥了面向对象编程的优势。
参考资料:[美]E.Winemiller,J.Roff B.Heyman,R.Groom著 顾 斌、杨德斌 译
清华大学出版社