单例、工厂与友元

单例、工厂与友元 (★★)

#abap-objects #singleton #factory #friendship

概览表

项目 关键点
单例模式 确保类只有一个实例
工厂模式 通过方法创建对象,隐藏实例化细节
友元关系 允许特定类访问私有组件
导航方法 返回关联对象引用的方法
构造器可见性 可以限制为 PRIVATE/PROTECTED

单例模式 (Singleton Pattern)

确保一个类只有一个实例并提供全局访问点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CLASS lcl_database DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: get_instance
RETURNING VALUE(ro_inst) TYPE REF TO lcl_database.
PRIVATE SECTION.
CLASS-DATA: mo_instance TYPE REF TO lcl_database.
METHODS: constructor.
ENDCLASS.

CLASS lcl_database IMPLEMENTATION.
METHOD get_instance.
IF mo_instance IS NOT BOUND.
CREATE OBJECT mo_instance.
ENDIF.
ro_inst = mo_instance.
ENDMETHOD.
METHOD constructor.
" 初始化
ENDMETHOD.
ENDCLASS.

实现要点

  1. 构造器设为 PRIVATE (CREATE PRIVATE)
  2. 静态属性保存唯一实例
  3. 静态方法 get_instance( ) 提供访问点
  4. 惰性初始化 — 首次调用时创建
1
2
调用者1: DATA(db) = lcl_database=>get_instance( ). ─→ [实例A]
调用者2: DATA(db2) = lcl_database=>get_instance( ). ─→ [实例A] ← 同一个!

工厂方法/工厂类 (Factory Pattern)

将对象创建逻辑封装到专门的方法或类中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CLASS lcl_vehicle_factory DEFINITION.
PUBLIC SECTION.
METHODS: create_vehicle
IMPORTING !iv_type TYPE string
RETURNING VALUE(ro_veh) TYPE REF TO lcl_vehicle.
ENDCLASS.

CLASS lcl_vehicle_factory IMPLEMENTATION.
METHOD create_vehicle.
CASE iv_type.
WHEN 'CAR'.
ro_veh = NEW lcl_car( ).
WHEN 'TRUCK'.
ro_veh = NEW lcl_truck( ).
WHEN 'BUS'.
ro_veh = NEW lcl_bus( ).
ENDCASE.
ENDMETHOD.
ENDCLASS.

工厂模式的优势

优势 说明
隐藏实例化细节 调用者不需要知道具体创建哪个类
集中创建逻辑 创建逻辑变化只需改工厂
配合构造器可见性限制 只能通过工厂创建对象

构造器可见性

1
2
3
" 限制构造器的可见性
CLASS lcl_car DEFINITION CREATE PRIVATE FRIENDS lcl_vehicle_factory.
" → 只有 lcl_vehicle_factory 能创建 lcl_car 实例

友元关系 (Friendship)

允许指定的类访问私有组件

1
2
3
4
CLASS lcl_vehicle DEFINITION FRIENDS lcl_vehicle_factory.
PRIVATE SECTION.
DATA: mv_serial TYPE string.
ENDCLASS.

友元规则

规则 说明
单向 A FRIENDS B → B可访问A的私有组件,反之不行
不继承 友元关系不传递给子类
可在定义时指定 CLASS ... DEFINITION FRIENDS friend_class.
⚠️友元是封装的例外
友元破坏了封装原则,应谨慎使用。仅在确实需要时使用(如工厂模式、测试类)。

导航方法 (Navigation Method)

返回关联对象引用的方法:

1
2
3
4
5
6
7
8
CLASS lcl_rental DEFINITION.
PUBLIC SECTION.
METHODS: get_vehicle
IMPORTING !iv_index TYPE i
RETURNING VALUE(ro_veh) TYPE REF TO lcl_vehicle.
PRIVATE SECTION.
DATA: mt_vehicles TYPE TABLE OF REF TO lcl_vehicle.
ENDCLASS.

链式方法调用 (7.0 EhP2+)

1
2
3
4
5
6
7
" 以前: 需要中间变量
DATA(lo_veh) = lo_rental->get_vehicle( 1 ).
DATA(lo_motor) = lo_veh->get_motor( ).
DATA(lv_power) = lo_motor->get_power( ).

" 现在: 直接链式调用
DATA(lv_power) = lo_rental->get_vehicle( 1 )->get_motor( )->get_power( ).

内表中对象引用的访问

1
2
3
4
5
6
7
8
9
" 使用公有只读属性作为键
READ TABLE mt_vehicles INTO DATA(lo_veh)
WITH KEY table_line->make = 'BMW'.

" 或使用 WHERE 子句
LOOP AT mt_vehicles INTO DATA(lo_veh)
WHERE table_line->make = 'BMW'.
" ...
ENDLOOP.
💡TABLE_LINE
当内表行类型不是结构而是基本类型(如 REF TO)时,使用 TABLE_LINE 作为泛型列名。

考试/测试模式

场景/关键词 答案
“单例模式核心” CREATE PRIVATE + 静态实例 + get_instance( )
“工厂方法的作用” 封装对象创建逻辑
“友元关系方向” 单向,不传递
“链式调用要求” 7.0 EhP2+ 支持
“构造器可见性” 可限制为 PRIVATE/PROTECTED