(这是一篇我几年前发表在IBM developerWorks上的文章,在此转帖,构成面向对象的LotusScript的系列文章之一篇,并为后续的讨论做准备。原来developerWorks上文章的格式要求在此页显示不太美观,稍作调整。有些英文粘贴后会被去掉中间的空格,没有检查到的就还会存在,请注意分词:)代码着色比原本的一色黑白好看很多。)
前言
事件是面向对象语言普遍支持和使用的一种模式。事件不仅在与用户交互的系统中应用很广泛,设计对象时恰当地采用事件对写出结构清晰、独立的代码也很有帮助。LotusScript支持事件,各个UI对象公布的事件在程序中都经常使用。不过在LotusScript支持的三种对象:Notes对象、自定义对象和OLE对象中,只有Notes对象支持事件。也就是说我们只能使用Notes类公布的事件,无法在自定义类中定义事件。
那么,是否可以在LotusScript模拟事件?
事件处理的核心就是当某个“状态”变化时一个程序(事件源event emitters)通知预订(subscribe)处理此事件的另一个程序(事件消费者event consumers),很多语言通过回调函数实现这样的机制。LotusScript不支持任何形式的“函数指针”,所以只能另想办法。
下面分析一个实际问题。
实现一
设想有一个资产管理的数据库,其中要处理诸如接收、转移、注销的多个流程。我们将处理流程的公共代码都放在一个流程类SimpleFlow中。具体的工作流只要创建一个SimpleFlow的实例然后调用它的Submit方法。每个流程会有一些特定的业务逻辑,比如在资产注销流程提交前,要检查一个Amount域的值,如果金额大于5000需要弹出一个对话框让用户输入更多信息;流程提交后再更新对应的资产文档。这些业务逻辑可以放在很多地方,比如在表单上提交动作的按钮或操作中,在调用SimpleFlow的Submit方法前后加入。如果采用事件的方式考虑,我们希望在Submit之前和之后分别引发事件QuerySubmit和PostSubmit,在它们的处理程序(eventhandlers)中添加流程实例特定的代码。
为了使讨论集中,本文的示例代码都只包含与主题相关的部分,不包含处理流程的细节以及错误处理代码。
SimpleFlow类(代码包含在一个名为SimpleFlowLib的Script Library中)
Public Class SimpleFlow
'定义公共对象变量
'流程变量
Private strFlow As String
Private strNode As String
Private strAction As String
'Notes对象
Private s As NotesSession
Private ws As NotesUIWorkspace
Private uidoc As NotesUIDocument
Private doc As NotesDocument
Private db As NotesDatabase
'下面是SimpleFlow公开的一些属性
Public Property Get FlowName As String
FlowName=strFlow
End Property
Public Property Get NodeName As String
NodeName=strNode
End Property
Public Property Get ActionName As String
ActionName=strAction
End Property
Public Property Get MainUIDoc As NotesUIDocument
Set MainUIDoc=uidoc
End Property
Public Pro