After completing this lesson, you will be able to:
After completing this lesson, you will be able to:
Use factory methods
Factory Methods
Sometimes a class needs to keep control of its instances. This could be to prevent multiple instances being created. In order to do so, it must prevent its users from creating instances themselves. You do this in ABAP by using the CREATE PRIVATE addition in the CLASS DEFINITION statement. Any attempt to use the NEW operator outside the class will now lead to a syntax error. Note that other programming languages achieve this effect by altering the visibility of the constructor method. ABAP does not support this.
Since users of the class cannot create their own instances, the class must then provide a public static method that creates instances and returns them to the user. This is called a factory method.
Try It Out: Factory Methods Implementation
Create a new class that implements the interface IF_OO_ADT_CLASSRUN.
Switch to the Local Types tab and copy the following code snippet into the editor:
Code snippet
CLASS lcl_connection DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
METHODS constructor
IMPORTING
airlineid TYPE /dmo/carrier_id
connectionnumber TYPE /dmo/connection_id
fromAirport TYPE /dmo/airport_from_id
toAirport TYPE /dmo/airport_to_id.
CLASS-METHODS get_connection IMPORTING airlineId TYPE /dmo/carrier_id
connectionNumber TYPE /dmo/connection_id
RETURNING VALUE(ro_connection) TYPE REF TO lcl_Connection.
PRIVATE SECTION.
DATA AirlineId TYPE /dmo/carrier_id.
DATA ConnectionNumber TYPE /dmo/connection_id.
DATA fromAirport TYPE /dmo/airport_from_id.
DATA toAirport TYPE /dmo/airport_to_id.
ENDCLASS.
CLASS lcl_connection IMPLEMENTATION.
METHOD constructor.
me->airlineid = airlineid.
me->connectionnumber = connectionnumber.
me->fromAirport = fromAirport.
me->toAirport = toAirport.
ENDMETHOD.
METHOD get_connection.
DATA fromAirport TYPE /dmo/airport_from_id.
DATA toAirport TYPE /dmo/airport_to_id.
SELECT SINGLE FROM /dmo/connection FIELDS airport_from_id, airport_to_id
WHERE carrier_id = @airlineid
AND connection_id = @connectionnumber
INTO ( @fromAirport, @toAirport ).
ro_connection = NEW #( airlineid = airlineid connectionnumber = connectionnumber fromairport = fromairport toairport = toairport ).
ENDMETHOD.
ENDCLASS.
Switch to the Global Class tab and paste the following code snippet into the implementation of method if_oo_adt_classrun~main( ):
Code snippet
CLASS zcl_s4d401_factory DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
interfaces if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_s4d401_factory IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
data connection type ref to lcl_connection.
* Debug the method to show that the class returns objects, but that there are different
* objects for the same combination of airline and flight number
connection = lcl_connection=>get_connection( airlineid = 'LH' connectionnumber = '0400' ).
connection = lcl_connection=>get_connection( airlineid = 'LH' connectionnumber = '0400' ).
ENDMETHOD.
ENDCLASS.
Play around with the coding. In particular, debug the main() method and note the internal instance numbers assigned to the objects returned by the factory method.
Singleton Pattern Implementation
The purpose of the singleton pattern is to ensure that there is only one instance of a class in an application. This could be a single instance of the class or, in our case, a single instance for each combination of key attributes.
Try It Out: Singleton Pattern Implementation
Create a new class that implements the interface IF_OO_ADT_CLASSRUN.
Switch to the Local Types tab and copy the following code snippet into the editor:
Code snippet
CLASS lcl_connection DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
METHODS constructor
IMPORTING
airlineid TYPE /dmo/carrier_id
connectionnumber TYPE /dmo/connection_id
fromAirport TYPE /dmo/airport_from_id
toAirport TYPE /dmo/airport_to_id.
CLASS-METHODS get_connection IMPORTING airlineId TYPE /dmo/carrier_id
connectionNumber TYPE /dmo/connection_id
RETURNING VALUE(ro_connection) TYPE REF TO lcl_Connection.
PRIVATE SECTION.
TYPES: BEGIN OF ts_instance,
airlineId TYPE /dmo/carrier_id,
connectionNumber TYPE /dmo/connection_id,
object TYPE REF TO lcl_connection,
END OF ts_instance,
tt_instances TYPE HASHED TABLE OF ts_instance
WITH UNIQUE KEY airlineId ConnectionNumber.
DATA AirlineId TYPE /dmo/carrier_id.
DATA ConnectionNumber TYPE /dmo/connection_id.
DATA fromAirport TYPE /dmo/airport_from_id.
DATA toAirport TYPE /dmo/airport_to_id.
CLASS-DATA connections TYPE tt_instances.
ENDCLASS.
CLASS lcl_connection IMPLEMENTATION.
METHOD constructor.
me->airlineid = airlineid.
me->connectionnumber = connectionnumber.
me->fromAirport = fromAirport.
me->toAirport = toAirport.
ENDMETHOD.
METHOD get_connection.
DATA fromAirport TYPE /dmo/airport_from_id.
DATA toAirport TYPE /dmo/airport_to_id.
IF NOT line_exists( connections[ airlineid = airlineid connectionnumber = connectionnumber ] ).
SELECT SINGLE FROM /dmo/connection FIELDS airport_from_id, airport_to_id
WHERE carrier_id = @airlineid
AND connection_id = @connectionnumber
INTO ( @fromAirport, @toAirport ).
ro_connection = NEW #( airlineid = airlineid connectionnumber = connectionnumber fromairport = fromairport toairport = toairport ).
DATA(new_instance) = VALUE ts_instance( airlineId = airlineId connectionnumber = connectionnumber object = ro_connection ).
INSERT new_instance INTO TABLE connections.
ELSE.
ro_connection = connections[ airlineId = airlineId connectionnumber = connectionnumber ]-object.
ENDIF.
ENDMETHOD.
ENDCLASS.
Switch to the Global Class tab and paste the following code snippet into the implementation of method if_oo_adt_classrun~main( ):
Code snippet
CLASS zcl_s4d401_factory_singleton DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
interfaces if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_s4d401_factory_singleton IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
data connection type ref to lcl_connection.
* Debug the method to show that the class always returns the same object
* for the same combination of airline and flight number
connection = lcl_connection=>get_connection( airlineid = 'LH' connectionnumber = '0400' ).
connection = lcl_connection=>get_connection( airlineid = 'LH' connectionnumber = '0400' ).
ENDMETHOD.
ENDCLASS.
Play around with the coding. In particular, debug the main() method and note the internal instance numbers assigned to the objects returned by the factory method.