首页 > 代码库 > ABAP OO与ALV结合方式探索(2)
ABAP OO与ALV结合方式探索(2)
接上篇
一开始设计的BO 类是为了实现功能而实现功能
从类的单一职责的角度而言
先把这个BO对象拆分
这里又有一个需要考虑的点: 如何传递内表数据到ALV
如果引入一个中间变量,数据就会被double
alv大量数据显示也是常有的事,再double一下显然不可取
而且alv中修改了数据还得把修改的数据传回去 想想就麻烦
于是就想到了引用类型,这是个不错的解决方案
后来又反思了一下,
是否真的需要引用类型,是否有必要遵守严格的OO属性不对外公开
从写代码更简单,更快交付而言
在这个模型中把 要显示的内表声明为public 似乎更好一点
CLASS lcl_bo DEFINITION. PUBLIC SECTION. METHODS: mock."模拟业务操作 DATA: gt_bo TYPE tt_bo.ENDCLASS.CLASS lcl_alv DEFINITION. PUBLIC SECTION. METHODS: config," alv 显示参数 display CHANGING ct_table TYPE ANY TABLE."alv* PRIVATE SECTION. DATA: gt_fieldcat TYPE lvc_t_fcat," 显示字段列表 gs_layout TYPE lvc_s_layo , " 页面布局 g_container TYPE REF TO cl_gui_custom_container, " 容器 g_grid TYPE REF TO cl_gui_alv_grid. " 显示GridENDCLASS.CLASS lcl_bo IMPLEMENTATION. METHOD mock. DATA: ls_bo TYPE ts_bo. DO 10 TIMES. ls_bo-datum = sy-datum + sy-index. ls_bo-uzeit = sy-uzeit. ls_bo-value = http://www.mamicode.com/‘Times:‘ && sy-index. APPEND ls_bo TO gt_bo.CLEAR ls_bo. ENDDO. ENDMETHOD.ENDCLASS.CLASS lcl_alv IMPLEMENTATION. METHOD config. DATA: ls_fieldcat TYPE lvc_s_fcat. ls_fieldcat-fieldname = ‘DATUM‘.ls_fieldcat-coltext = ‘日期‘. APPEND ls_fieldcat TO gt_fieldcat.CLEAR ls_fieldcat. ls_fieldcat-fieldname = ‘UZEIT‘.ls_fieldcat-coltext = ‘时间‘. APPEND ls_fieldcat TO gt_fieldcat.CLEAR ls_fieldcat. ls_fieldcat-fieldname = ‘VALUE‘.ls_fieldcat-coltext = ‘内容‘. APPEND ls_fieldcat TO gt_fieldcat.CLEAR ls_fieldcat. gs_layout-sel_mode = ‘A‘. gs_layout-zebra = ‘X‘ . gs_layout-cwidth_opt = ‘X‘. ENDMETHOD. METHOD display. IF g_grid IS INITIAL. CREATE OBJECT g_container EXPORTING container_name = ‘C0100‘. CREATE OBJECT g_grid EXPORTING i_parent = g_container. CALL METHOD g_grid->set_table_for_first_display EXPORTING* I_BUFFER_ACTIVE =* I_CONSISTENCY_CHECK =* I_STRUCTURE_NAME =* is_variant = gs_variant i_save = ‘A‘ i_default = ‘X‘* is_layout = gs_layout* IS_PRINT =* IT_SPECIAL_GROUPS =* it_toolbar_excluding = gt_exclude* IT_HYPERLINK = CHANGING it_outtab = ct_table it_fieldcatalog = gt_fieldcat* it_sort = gt_sort* IT_FILTER = EXCEPTIONS invalid_parameter_combination = 1 program_error = 2 too_many_lines = 3 OTHERS = 4. ELSE. CALL METHOD g_grid->refresh_table_display. ENDIF. ENDMETHOD. "displayENDCLASS.DATA: ok_code TYPE sy-ucomm, go_bo TYPE REF TO lcl_bo, go_alv TYPE REF TO lcl_alv.START-OF-SELECTION. CREATE OBJECT go_bo. CREATE OBJECT go_alv. go_bo->mock( ). go_alv->config( ). CALL SCREEN 100.MODULE status_0100 OUTPUT. SET PF-STATUS ‘PS100‘. go_alv->display( CHANGING ct_table = go_bo->gt_bo ).ENDMODULE. " STATUS_0100 OUTPUTMODULE user_command_0100 INPUT. CASE ok_code. WHEN ‘BACK‘. SET SCREEN 0. ENDCASE.ENDMODULE. " USER_COMMAND_0100 INPUT
效果如下:
这个模型应该比上一个要好一点
BO中只关注业务逻辑,怎么显示全部交给ALV
如果严格的说遵循一些OO的编程规范
gt_bo是不可以放在public sction中的
那么传递数据使用需要稍微作一个变化
bo对象增加一个get_ref_table的方法
返回引用,对应的alv的display方法传入引用类型参数
代码就不写了
(在后续会讨论重用ALV对象
如果采用引用传递的话还有一个变化
定义一个通用接口 ,接口中就一个方法获取输出内表的引用
BO对象都要实现这个接口
ALV的display方法传入的参数就是这个接口对象)
* 这篇文章也是在上线期间事情不多的时候陆陆续续写的
* 又开始忙起来了,之后更新的速度可能就慢了(或者说又开始懒了)
* 大致把后续的思路也说一下吧
在当前模式下
一个BO 对应一个ALV
一般复杂一点的报表会有多个BO
也就有多个ALV
很自然会发现ALV的部分代码都是重复的
后续会讨论用抽象类实现ALV的基本功能
子类只关注fieldcat的编码
以及如何扩展抽象类的功能
使其适应项目中不同场景的要求
例如,隐藏工具栏,增加输出列,保持选中,启用变式等等
以及如何适应未来没有考虑到的扩展场景(其实就是预留一些方法,给子类重写而已)
当做到这一步的时候
其实会发现SAP已经帮我们都把这些事情做得差不多了
把我们的OO代码 同SAP的 REUSE_ALV_GRID_DISPLAY 结合
就是目前一直在做的事情
但是自定义的ALV有一个好处
可以把这个模型用到复杂的对话屏幕中
除了ALV还有其他控件
所以自定义的ALV还是有用武之地的
如果单纯的做报表
那么推荐 OO + REUSE_ALV_GRID_DISPLAY
OO的代码处理核心业务逻辑
(还可以引入一些简单的设计模式,报表开发就会很happy~)
同时自定义的控件中封装REUSE_ALV_GRID_DISPLAY 显示也变得很简单
后续还会再写几个不同场景的示例出来
都是个人的一些思路,欢迎交流.
待续吧…
ABAP OO与ALV结合方式探索(2)