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

 

原文地址: 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


运行结果:

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值