ABAP实现设计模式里的观察者-发布者模式
This is an interview question from Wechat development team. The candidates are required to answer with JavaScript. Nevertheless I think it is also beneficial for an ABAPer if we master the design pattern contained in this question –Publish and Subscribe pattern.
The requirement
(1) The chain operations could be performed on instance of class ZCL_PERSON. For example, the red line 10 in ABAP code should generate the following output highlighted in red, and blue and green color accordingly. (2) The “sleep_first” operation has the highest priority, see ABAP line 14 and its output for reference.
Some keypoints to finish this question
(1) the operation call must support chain invoke style, which means each call must return current instance as returning parameter. (2) In order to support the prioritization of Sleep first operation, during each operation call, the activity must not be executed immediately, or else the Sleep first operation will never have chance to be shifted to call before others. Instead, the detail information of each operation should be subscribed into a task queue, so that when a new element is inserted into that queue, we can have flexibility to adapt the order of each element in the queue, that is, if the Sleep first call is enqueued, it must always be positioned in the queue header. The signature and implementation of subscribe method:
When eat or sleep is called, simply log it via subscribe method and return current instance for chain invoke.
The declaration of the series of calls ends up with method done, which calls private publish method, which loops all elements in the task queue and deal with each one by one.
The do_task has a CASE-WHEN structure to dispatch the call to dedicated handler method according to operation type:
The complete source code of ZCL_PERSON.
CLASS zcl_person DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
METHODS done .
METHODS constructor
IMPORTING
!iv_name TYPE string .
METHODS eat
IMPORTING
!iv_sth TYPE string
RETURNING
VALUE(ro_this) TYPE REF TO zcl_person .
METHODS sleep
IMPORTING
!iv_seconds TYPE int4
RETURNING
VALUE(ro_this) TYPE REF TO zcl_person .
METHODS sleep_first
IMPORTING
!iv_seconds TYPE int4
RETURNING
VALUE(ro_this) TYPE REF TO zcl_person .
PROTECTED SECTION.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_task,
task_type TYPE string,
task_param TYPE string,
END OF ty_task .
TYPES:
tt_task TYPE STANDARD TABLE OF ty_task WITH KEY task_type task_param .
DATA mt_task TYPE tt_task .
METHODS perform_eat
IMPORTING
!iv_sth TYPE string .
METHODS subscribe
IMPORTING
!iv_type TYPE string
!iv_param TYPE string .
METHODS publish .
METHODS do_task
IMPORTING
!is_task TYPE ty_task .
METHODS perform_sleep
IMPORTING
!iv_param TYPE string .
ENDCLASS.
CLASS ZCL_PERSON IMPLEMENTATION.
METHOD constructor.
WRITE: / 'Hello, I am ' , iv_name.
ENDMETHOD.
METHOD done.
publish( ).
ENDMETHOD.
METHOD do_task.
CASE is_task-task_type.
WHEN 'eat'.
perform_eat( is_task-task_param ).
WHEN 'sleep' OR 'sleepFirst'.
perform_sleep( is_task-task_param ).
WHEN OTHERS.
ENDCASE.
ENDMETHOD.
METHOD eat.
subscribe( iv_type = 'eat' iv_param = iv_sth ).
ro_this = me.
ENDMETHOD.
METHOD perform_eat.
WRITE: / 'eat ' , iv_sth.
ENDMETHOD.
METHOD perform_sleep.
DATA(lv_second) = CONV int4( iv_param ).
WAIT UP TO lv_second SECONDS.
WRITE:/ ' wake up after sleep for ' , iv_param, ' seconds.'.
ENDMETHOD.
METHOD publish.
LOOP AT mt_task ASSIGNING FIELD-SYMBOL(<task>).
do_task( <task> ).
ENDLOOP.
CLEAR: mt_task.
ENDMETHOD.
METHOD sleep.
subscribe( iv_type = 'sleep' iv_param = CONV string( iv_seconds ) ).
ro_this = me.
ENDMETHOD.
METHOD sleep_first.
subscribe( iv_type = 'sleepFirst' iv_param = CONV string( iv_seconds ) ).
ro_this = me.
ENDMETHOD.
METHOD subscribe.
DATA(ls_task) = VALUE ty_task( task_type = iv_type task_param = iv_param ).
IF iv_type = 'sleepFirst'.
INSERT ls_task INTO mt_task INDEX 1.
ELSE.
APPEND ls_task TO mt_task.
ENDIF.
ENDMETHOD.
ENDCLASS.
Test report:
REPORT ZSUBSCRIBER.
data(jerry) = new ZCL_PERSON( 'Jerry' ).
jerry->eat( 'breakfast' )->eat( 'lun' )->eat( 'supper' )->done( ).
jerry->eat( 'apple' )->sleep( 1 )->eat( 'pear' )->done( ).
jerry->eat( 'banana' )->sleep_first( 1 )->eat( 'grape' )->done( ).
- HDU 1003 Max Sum【动态规划求最大子序列和详解 】
- HDU 1005 Number Sequence【多解,暴力打表,鸽巢原理】
- HDU 1019 Least Common Multiple【gcd+lcm+水+多个数的lcm】
- HDU 1017 A Mathematical Curiosity【水,坑】
- 比特币项目
- HDU 1014 Uniform Generator【GCD,水】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战05】SARSA(λ)算法实现
- 区块链应用场景:物联网和物流供应链
- HDU 1012 u Calculate e【暴力打表,水】
- Gym 100952C&&2015 HIAST Collegiate Programming Contest C. Palindrome Again !!【字符串,模拟】
- HDU 1013 Digital Roots【字符串,水】
- Gym 100952I&&2015 HIAST Collegiate Programming Contest I. Mancala【模拟】
- bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序
- Gym 100952E&&2015 HIAST Collegiate Programming Contest E. Arrange Teams【DFS+剪枝】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 批量执行crontab指定条目的注释和解注释
- Rancher集群部署后需要做的几件事
- Ingress(Nginx)日志持久化与可视化(多图预警)
- .Net在Windows上使用Jenkins做CI/CD的那些事
- 【STM32H7】第9章 RL-TCPnet调试方法(Event Recorder和串口两种)
- 【STM32F429】第9章 RL-TCPnet调试方法(Event Recorder和串口两种)
- 【STM32F407】第9章 RL-TCPnet V7.X调试方法(Event Recorder和串口两种)
- CentOS7的udev的绑定规则
- 案例:记录一则强制开库遭遇ORA-16433的处理过程
- mybatis升级为mybatis-plus踩到的坑
- Treepath
- linux 远程ssh免密登录
- npm 安装 electron taobao镜像 404错误 自用 实践笔记
- Asp.net Core 使用Jenkins + Dockor 实现持续集成、自动化部署(二):部署
- 队列的一种实现:循环队列