ABAP OO的八大理由(十二)
原因五,事件
应用中,用户界面的鼠标单击,新帐户的建立,都可以触发一个事件,这个事件要被他感兴趣的处理者知道。事件和事件处理与调用过程有相似之处:触发事件就相当于调用自程序,处理事件就相当于被调用子程序的主程序。区别是被调用的子程序和调用程序是帮定的一块儿的,而事件则不同,处理者有可能处理触发的事件,但也不一定。面向过程的ABAP的事件处理是通过运行时来实现的。而在OO中,类和对象既可以触发事件,又可以处理事件。下面将详细讨论这两种模式对事件处理的支持。
面向过程的事件处理
对于面向过程的ABAPER来说事件的概念可以说是再熟悉不过了。没有事件你就无法执行ABAP程序。要想通过SUBMIT来执行一个程序,那么它必须有个start-of-selection的事件,它是由运行时触发的。对于屏幕处理逻辑,必须能够处理PBO和PAI事件。另外在SELECTION SCREEN中你还可以处理AT SELECTION-SCREEN事件,在LIST中处理AT-LINE-SELECTION事件和AT USER-COMMAND事件。
面向过程事件的一个问题便是他的隐含性。除了两个例外外,你无法在程序里触发事件,这两个例外是在逻辑数据库的程序里可以通过PUT触发GET事件。通过SET USER-COMMAND触发AT USER-COMMAND事件。其次便是为了写好ABAP程序,你必须了解特殊的处理流程,比如报表程序流程,对话业务流程,selection screen流程,list流程等。最后,你无法编写和处理自己的事件。这就意味着调用者和被调用模块间是一种紧密联系,一旦你在某个地方调用了某个模块,要么这个模块存在要么就会出现运行时错误。
OO模式下的事件处理
在ABAP OO中,事件是作为类中的一部分被显式声明的。如果一个事件在类中已经被声明,那么在这个类的方法中可以通过RAISE EVENT来触发它。通过RAISE EVENT除了告诉系统即将触发一个事件外还可以通过它来传递参数给它的处理者。这个处理者便是其他类或者该类中的一个方法。这个方法静态的定义为某个具体事件的处理者。在程序的运行过程当中事件处理者可以随时被动态的激活或使其失效,并且一个事件可以同时拥有多个事件处理者。
ABAP OO中事件处理的好处便是调用者和被调用者之间的分离。不是调用方法,而是通过触发事件来调用这个事件所有的处理者(即静态的定义好事件的处理者然后在运行时动态的激活它)。这与传统的面向过程模式正好相反,调用者必须明确的知道它要调用什么。发布和调用的两个状态,即事件处理者的静态定义和事件处理的动态激活为事件编程带来了很大的灵活性。下面的例子演示了如何是我们的银行帐号能够处理事件。
CLASS checking_account DEFINITION INHERIATING FROM account.
PUBLIC SECTION.
METHODS deposit REDEFINITION.
….
EVENTS adivising_required
EXPORTING value(amount) TYPE accounts-amount.
PRIVATE SECTION.
DATA: limit TYPE accounts-amount VALUE ‘5000.00’.
ENDCLASS.
CLASS checking_account IMPLEMENTATION.
METHOD deposit.
Super->deposit( amount ).
IF me->amount > limit.
RAISE EVENT advising_required
EXPORTING amount = me->amount.
ENDIF.
ENDMETHOD.
ENDCLASS.
CLASS advisor DEFINITION.
PUBLIC SECTION.
METHODS constructor.
….
PRIVATE SECTION.
….
METHODS receive_notification.
FOR EVENT advising_required OF checking_account.
ENDCLASS.
CLASS advisor IMPLEMENTATION.
METHOD constructor.
…
IF …
SET HANDLER me-receive_notification FOR ALL INSTANCES.
ENDIF.
ENDMETHOD.
…..
METHOD receive_notification.
“do something
ENDMETHOD.
ENDCLASS.
这里子类checking_account增加了事件advising_required.这个事件在重写的deposit的方法中当amount超过limit的时候触发。在另一个类advisor中为事件advising_required定义了处理者receive_notification。在结构方法中,通过if块决定了那些银行帐号可以触发事件。在我们的例子了advisor对象将会响应任何一个银行账号的事件,当然你也可以在SET HANDLER语句中通过single object来替换ALL INSTANCES来限制触发事件的银行账号。这样你就可以做到通过特定的银行帐号来触发advisor的receive_notification方法。