观察者模式也称“发布-订阅模式(Pubish/Subscribe)”, “模型-视图模式(Model/View)”, “源-监听器模式(Source/Linster)”或者“从属者模式(Dependents)”, 它是一种行为型模式。
此种模式定义了一种“一对多”的依赖关系,多个观察者可同时监听某一个主题对象,当主题对象状态改变时,其相关的依赖对象皆得到通知,并自动更新自己。
类比:
解析:
要点:
设计模式对比:
在此例中,我们使用Pull方式来进行“观察者”和“发布者”间数据的交互。
每当有书籍返还时,将返还书籍的信息更新给所有的User。
REPORT zobserver_pattern.
INTERFACE lif_observer DEFERRED.
CLASS lcl_book_info DEFINITION DEFERRED.
**********************************************************************
" define an interface for publisher
INTERFACE lif_observable.
METHODS register_observer
IMPORTING
io_observer TYPE REF TO lif_observer.
METHODS delete_observer
IMPORTING
io_observer TYPE REF TO lif_observer.
METHODS notify_observer.
ENDINTERFACE.
**********************************************************************
" define an interface for subscriber
INTERFACE lif_observer.
METHODS update.
ENDINTERFACE.
**********************************************************************
" Book class is a publisher class enabled with observable interface
CLASS lcl_book_info DEFINITION FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES lif_observable.
METHODS get_book_status RETURNING VALUE(rv_status) TYPE string.
METHODS return_book IMPORTING iv_book_name TYPE string.
PRIVATE SECTION.
DATA mv_book_status TYPE string.
DATA mt_observers TYPE TABLE OF REF TO lif_observer.
ENDCLASS.
CLASS lcl_book_info IMPLEMENTATION.
METHOD lif_observable~delete_observer.
DELETE mt_observers WHERE table_line = io_observer.
ENDMETHOD.
METHOD lif_observable~register_observer.
APPEND io_observer TO mt_observers.
ENDMETHOD.
METHOD lif_observable~notify_observer.
LOOP AT mt_observers INTO DATA(lo_observer).
lo_observer->update( ).
ENDLOOP.
ENDMETHOD.
METHOD return_book.
" when something happens in publisher, it can decide whether it is a subscriber relevant
" if yes, notify subscriber
CONCATENATE 'Book "' iv_book_name '" is returned."' INTO mv_book_status.
me->lif_observable~notify_observer( ).
ENDMETHOD.
METHOD get_book_status.
rv_status = mv_book_status.
ENDMETHOD.
ENDCLASS.
**********************************************************************
" User class is subscriber class enabled with observer interface
CLASS lcl_library_user DEFINITION FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES lif_observer.
METHODS constructor
IMPORTING
iv_user_name TYPE string
io_book_info TYPE REF TO lcl_book_info.
PROTECTED SECTION.
DATA mv_book_status TYPE string.
PRIVATE SECTION.
DATA mo_book_info TYPE REF TO lcl_book_info.
DATA mv_user_name TYPE string.
METHODS output_info.
ENDCLASS.
CLASS lcl_library_user IMPLEMENTATION.
METHOD constructor.
mv_user_name = iv_user_name.
mo_book_info = io_book_info.
ENDMETHOD.
METHOD output_info.
WRITE: / mv_user_name, ' Know ', mv_book_status.
ENDMETHOD.
" obtain the reference from publisher, then do actions in subscriber
METHOD lif_observer~update.
mv_book_status = mo_book_info->get_book_status( ).
output_info( ).
ENDMETHOD.
ENDCLASS.
**********************************************************************
START-OF-SELECTION.
**********************************************************************
" Declare publisher and register subscriber
DATA(lo_book_info) = NEW lcl_book_info( ).
DATA(lo_user_a) = NEW lcl_library_user( io_book_info = lo_book_info iv_user_name = 'User-A' ).
DATA(lo_user_b) = NEW lcl_library_user( io_book_info = lo_book_info iv_user_name = 'User-B' ).
lo_book_info->lif_observable~register_observer( lo_user_a ).
lo_book_info->lif_observable~register_observer( lo_user_b ).
" Book returned, publisher will notify subscribers
lo_book_info->return_book( '<>' ).
" Delete subscribe for user-b
lo_book_info->lif_observable~delete_observer( lo_user_b ).
lo_book_info->return_book( '<>' ).
相同的应用场景,我们也可使用ABAP OO中的Event实现。
此例中,在lcl_book_info中我们定义的 book_returned 事件, lcl_library_user类则实现对此事件的监听。
REPORT zobserver_pattern2.
CLASS lcl_book_info DEFINITION FINAL CREATE PUBLIC.
PUBLIC SECTION.
METHODS get_book_status
RETURNING VALUE(rv_status) TYPE string.
METHODS return_book
IMPORTING iv_book_name TYPE string.
EVENTS book_returned.
PRIVATE SECTION.
DATA mv_book_status TYPE string.
ENDCLASS.
CLASS lcl_book_info IMPLEMENTATION.
METHOD get_book_status.
rv_status = mv_book_status.
ENDMETHOD.
METHOD return_book.
CONCATENATE 'Book "' iv_book_name '" is returned."' INTO mv_book_status.
RAISE EVENT book_returned.
ENDMETHOD.
ENDCLASS.
**********************************************************************
CLASS lcl_library_user DEFINITION FINAL CREATE PUBLIC.
PUBLIC SECTION.
METHODS constructor
IMPORTING
iv_user_name TYPE string.
METHODS on_book_returned FOR EVENT book_returned OF lcl_book_info
IMPORTING sender.
PROTECTED SECTION.
DATA mv_book_status TYPE string.
PRIVATE SECTION.
DATA mv_user_name TYPE string.
METHODS output_info.
ENDCLASS.
CLASS lcl_library_user IMPLEMENTATION.
METHOD constructor.
mv_user_name = iv_user_name.
ENDMETHOD.
METHOD output_info.
WRITE: / mv_user_name, ' Know ', mv_book_status.
ENDMETHOD.
METHOD on_book_returned.
mv_book_status = sender->get_book_status( ).
output_info( ).
ENDMETHOD.
ENDCLASS.
**********************************************************************
START-OF-SELECTION.
**********************************************************************
" Declare publisher and register subscriber
DATA(lo_book_info) = NEW lcl_book_info( ).
DATA(lo_user_a) = NEW lcl_library_user( 'User-A' ).
DATA(lo_user_b) = NEW lcl_library_user( 'User-B' ).
SET HANDLER lo_user_a->on_book_returned FOR lo_book_info.
SET HANDLER lo_user_b->on_book_returned FOR lo_book_info.
" Book returned, publisher will notify subscribers
lo_book_info->return_book( '<>' ).
以上,是本篇对观察者模式的总结,希望对您有所帮助,欢迎分享、留言。
本博客专注于技术分享,干货满满,持续更新。
欢迎关注❤️、点赞、转发!