您的位置:首页 > 其它

ABAP与设计模式之观察者模式

2013-07-01 15:19 411 查看
原文地址: http://database.chinaunix.net/a2009/0731/616/000000616610.shtml
观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。http://baike.baidu.com/view/1854779.htm

这章我们介绍观察者模式,下面先给出观察者模式的例子的类图:



首先给出测试程序的代码:

REPORT  zgary_t008.

INCLUDE zgary_t008_class_define.

"Declare data
DATA:
wd TYPE REF TO weather_data, " Weather data class reference object
su TYPE REF TO subject, " Define subject interface reference object
cu TYPE REF TO current_condition_display, " concrete observers object
" crrent condition object
sd TYPE REF TO statistics_display. " For statistics data object

START-OF-SELECTION.

CREATE OBJECT wd. " Create weather data object.

su ?= wd. " Widening cast,make the subject interface reference to
" weather data class

" Register concrete obsever to subject interface which
" point to weather data object
" For concrete observer current condition display
CREATE OBJECT cu
EXPORTING
wd = su.

" For concrete observer statistics data
CREATE OBJECT sd
EXPORTING
wd = su.

CALL METHOD wd->set_measurements
EXPORTING
tem = '80'
hum = '80'
pre = '80'.

CALL METHOD wd->set_measurements
EXPORTING
tem = '81'
hum = '82.4'
pre = '80'.

CALL METHOD wd->set_measurements
EXPORTING
tem = '79'
hum = '80'
pre = '80'.

*&---------------------------------------------------------------------*
*&  Include           ZGARY_T008_CLASS_DEFINE
*&---------------------------------------------------------------------*

*下面是三个interface:
*Interface definition.
*Interface for observer which just have one method, update()
INTERFACE observer.

METHODS:
" When the subject's data changed, it will update observer's data
update
IMPORTING temp TYPE f
hum  TYPE f
pre  TYPE f.

ENDINTERFACE.                    "observer

*interface for subject which used to operating observers
INTERFACE subject.

METHODS:
" register observer to subject
register_observer IMPORTING o TYPE REF TO observer,

" delete observer in subject
remove_observer IMPORTING o TYPE REF TO observer,

" notify observer that the status or data changed
notify_observer.

ENDINTERFACE.                    "observer

*interface for display data

INTERFACE display_element.

METHODS:

" when data changed in subject, the observers could
" call this behavior to display data after they receive
" the changed data
display.

ENDINTERFACE.                    "observer

*下面定义一个具体的主题:
*Define concrete subject
*In our example, we define a weather data object which
*implement the subject interface

CLASS weather_data DEFINITION.

PUBLIC SECTION.

" Define the interface
INTERFACES:
subject.

METHODS:
" The data change method
measurement_changed,

" Setter method for setting the weather data
set_measurements
IMPORTING tem TYPE f
hum TYPE f
pre TYPE f.

PRIVATE SECTION.

" The structure and internal table of observers
DATA: BEGIN OF r_observers,
observer TYPE REF TO observer,
END OF r_observers.

DATA: t_observers LIKE TABLE OF r_observers.

" Instance data definition
DATA hum TYPE f.
DATA pre TYPE f.
DATA tem TYPE f.

ENDCLASS.                    "weather_data DEFINITION

* Implement weather data
CLASS weather_data IMPLEMENTATION.

" Implement interface method
METHOD subject~register_observer.

"Get the import observer object
"and add it to observer's table
r_observers-observer = o.
APPEND r_observers TO t_observers.

ENDMETHOD.                    "subject~register_observer

METHOD subject~remove_observer.

"Delete observer
DELETE t_observers WHERE observer = o.

ENDMETHOD.                    "subject~remove_observer

METHOD subject~notify_observer.

" Notify observers
LOOP AT t_observers INTO r_observers.
"Update observers' data according to the subject changed data
CALL METHOD r_observers-observer->update
EXPORTING
temp = tem
hum  = hum
pre  = pre.
ENDLOOP.

ENDMETHOD.                    "subject~notify_observer

METHOD measurement_changed.
"when data changed, inform observer
CALL METHOD subject~notify_observer.
ENDMETHOD.                    "measurement_changed

METHOD set_measurements.
" set data of weather
me->tem = tem.
me->hum = hum.
me->pre = pre.
CALL METHOD measurement_changed.
ENDMETHOD.                    "set_measurements

ENDCLASS.                    "weather_data IMPLEMENTATION

*下面定义一个具体的观察者:current_condition_display
*Concrete observers
*Display current weather data
CLASS current_condition_display DEFINITION.

PUBLIC SECTION.

" Implement two interfaces, observer and display_element

INTERFACES:
observer,
display_element.

METHODS:
" Get the initial concrete subject object
constructor
IMPORTING wd TYPE REF TO subject.

PRIVATE SECTION.
DATA: tem TYPE f,
hum TYPE f.

"Concrete subject
DATA w_data TYPE REF TO weather_data.

ENDCLASS.                    "current_condition_display DEFINITION

*----------------------------------------------------------------------*
*       CLASS current_condition_display IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS current_condition_display IMPLEMENTATION.

"Update data
METHOD observer~update.

me->tem = temp.

me->hum = hum.

CALL METHOD display_element~display.

ENDMETHOD.                    "observer~update

" Display data
METHOD display_element~display.
WRITE: / 'Current conditions:'.
WRITE: / me->tem DECIMALS 2 EXPONENT 0, 'F degrees.'.
WRITE: / me->hum DECIMALS 2 EXPONENT 0, '% humidity.'.
ENDMETHOD.                    "display_element~display

METHOD constructor.
" Widening cast because wd's type which import is interface subject
" and the me->w_data's type is weather_data
" and weather data is more specialized than interface subject
me->w_data ?= wd.

" Register current condition observer to subject
CALL METHOD w_data->subject~register_observer
EXPORTING
o = me.
ENDMETHOD.                    "constructor

ENDCLASS.                    "current_condition_display IMPLEMENTATION

*下面定义另外一个观察者:statistics_display
*display statistics data
*----------------------------------------------------------------------*
*       CLASS statistics_display DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS statistics_display DEFINITION.
PUBLIC SECTION.
" Implement two interfaces, observer and display_element
INTERFACES:
observer,
display_element.
METHODS:
" Get the initial concrete subject object
constructor
IMPORTING wd TYPE REF TO subject.

PRIVATE SECTION.
DATA: av_temp TYPE f, "Average temperature
mx_temp TYPE f, "Max temperature
mi_temp TYPE f. "Min temperature
DATA: wd TYPE REF TO weather_data.
ENDCLASS.                    "current_condition_display IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS statistics_display IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS statistics_display IMPLEMENTATION.
METHOD constructor.
" Register observer
me->wd ?= wd.
CALL METHOD me->wd->subject~register_observer
EXPORTING
o = me.
ENDMETHOD.                    "constructor

METHOD observer~update.
" Local data definition
" Table record number
DATA: num TYPE i.
" Local cal data
DATA:
tav_temp TYPE f,
tmx_temp TYPE f,
tmi_temp TYPE f.
" Store all the temperature which setted
DATA:
BEGIN OF r_result,
temp TYPE f,
END OF r_result.
DATA: t_result LIKE TABLE OF r_result.
" Get the temperature and add it to table
r_result-temp = temp.
APPEND r_result TO t_result.
DESCRIBE TABLE t_result LINES num.
IF num <> 0.
SORT t_result ASCENDING.
" Get min temp
READ TABLE t_result INDEX 1 INTO r_result.
tmi_temp = r_result-temp.

" Get max temp
READ TABLE t_result INDEX num INTO r_result.
tmx_temp = r_result-temp.

" Get avg temp
LOOP AT t_result INTO r_result.
tav_temp = tav_temp + r_result-temp.
ENDLOOP.
tav_temp = tav_temp / num .

" update instance variants
mi_temp = tmi_temp.
mx_temp = tmx_temp.
av_temp = tav_temp.
ENDIF.
"Display result
CALL METHOD display_element~display.
ENDMETHOD.                    "observer~update

METHOD display_element~display.
SKIP.
WRITE: / 'Statistics display:'.
WRITE: / 'Average temp:', av_temp DECIMALS 2 EXPONENT 0.
WRITE: / 'Max temp:',     mx_temp DECIMALS 2 EXPONENT 0.
WRITE: / 'Min temp:',     mi_temp DECIMALS 2 EXPONENT 0.
ENDMETHOD.                 "display_element~display
ENDCLASS.                    "statistics_display IMPLEMENTATION


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: