* create objects CREATE OBJECT h1.
CREATE OBJECT h2.
CREATE OBJECT h3.
h1->setsuccessor( h2 ).
h2->setsuccessor( h3 ).
INSERT 2 INTO TABLE t_request.
INSERT 5 INTO TABLE t_request.
INSERT 14 INTO TABLE t_request.
INSERT 22 INTO TABLE t_request.
INSERT 18 INTO TABLE t_request.
INSERT 3 INTO TABLE t_request.
INSERT 27 INTO TABLE t_request.
INSERT 20 INTO TABLE t_request.
LOOP AT t_request INTO request.
h1->handlerequest( request ).
ENDLOOP.
ENDMETHOD. "constructor
ENDCLASS. "lcl_application IMPLEMENTATION START-OF-SELECTION.
lcl_application=>run( ).
2.3.1.6 Sample code In C#
This real-world code demonstrates the Chain of Responsibility pattern in which several linked managers and executives can respond to a purchase request or hand it off to a superior. Each position has can have its own set of rules which orders they can approve.
// Chain of Responsibility pattern -- Real World example using System;
namespace DoFactory.GangOfFour.Chain.RealWorld {
// MainApp test application
class MainApp {
static void Main() {
// Setup Chain of Responsibility Director Larry = new Director();
VicePresident Sam = new VicePresident();
President Tammy = new President();
Larry.SetSuccessor(Sam);
Project: Design Pattern
Sam.SetSuccessor(Tammy);
// Generate and process purchase requests
Purchase p = new Purchase(2034, 350.00, "Supplies");
Larry.ProcessRequest(p);
p = new Purchase(2035, 32590.10, "Project X");
Larry.ProcessRequest(p);
p = new Purchase(2036, 122100.00, "Project Y");
Larry.ProcessRequest(p);
// Wait for user Console.Read();
} }
// "Handler"
abstract class Approver {
protected Approver successor;
public void SetSuccessor(Approver successor) {
this.successor = successor;
}
public abstract void ProcessRequest(Purchase purchase);
}
// "ConcreteHandler"
class Director : Approver {
public override void ProcessRequest(Purchase purchase) {
if (purchase.Amount < 10000.0) {
Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number);
}
else if (successor != null) {
successor.ProcessRequest(purchase);
} } }
// "ConcreteHandler"
class VicePresident : Approver {
public override void ProcessRequest(Purchase purchase) {
if (purchase.Amount < 25000.0)
Project: Design Pattern
{
Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number);
}
else if (successor != null) {
successor.ProcessRequest(purchase);
} } }
// "ConcreteHandler"
class President : Approver {
public override void ProcessRequest(Purchase purchase) {
if (purchase.Amount < 100000.0) {
Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number);
} else {
Console.WriteLine(
"Request# {0} requires an executive meeting!", purchase.Number);
} } }
// Request details
class Purchase {
private int number;
private double amount;
private string purpose;
// Constructor
public Purchase(int number, double amount, string purpose) {
this.number = number;
this.amount = amount;
this.purpose = purpose;
}
// Properties public double Amount {
get{ return amount; } set{ amount = value; } }
public string Purpose {
Project: Design Pattern
get{ return purpose; } set{ purpose = value; } }
public int Number {
get{ return number; } set{ number = value; } }
} } Output
Director Larry approved request# 2034 President Tammy approved request# 2035 Request# 2036 requires an executive meeting!
2.3.1.7 Sample code In ABAP
This real-world code demonstrates the Chain of Responsibility pattern in which several linked managers and executives can respond to a purchase request or hand it off to a superior. Each position has can have its own set of rules which orders they can approve.
*&---*
*& Report ZDP_CHAINOFRESP_REALWORLD
*&
*&---*
*&
*&
*&---*
REPORT zdp_chainofresp_realworld.
CLASS cl_abap_typedescr DEFINITION LOAD.
*---*
* Global Data
*---*
DATA: moff TYPE i ,slen TYPE i ,mlen TYPE i.
*---*
* Macro ?get_class_name returns the class name of the class
* Importing &1 Any Class
* Exporting &2 The name of the Class &1
*---*
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
*---*
* CLASS purchase DEFINITION
*---*
Project: Design Pattern
,get_property IMPORTING name TYPE stringRETURNING value(dref) TYPE REF TO data.
METHOD constructor.
me->number = number.
me->amount = amount.
me->purpose = purpose.
ENDMETHOD. "constructor METHOD get_property.
CASE name.
CLASS approver DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,setsuccessor IMPORTING successor TYPE REF TO approver
,processrequest ABSTRACT IMPORTING purchase TYPE REF TO purchase . PROTECTED SECTION.
DATA: name TYPE string.
DATA: successor TYPE REF TO approver.
ENDCLASS. "approver DEFINITION
*---*
Project: Design Pattern
* CLASS approver IMPLEMENTATION
*---*
*
*---*
CLASS approver IMPLEMENTATION.
METHOD constructor.
me->name = name.
ENDMETHOD. "constructor METHOD setsuccessor.
me->successor = successor.
ENDMETHOD. "SetSuccessor
ENDCLASS. "approver IMPLEMENTATION
*---*
* CLASS Director DEFINITION
*---*
*
*---*
CLASS director DEFINITION INHERITING FROM approver.
PUBLIC SECTION.
METHODS:
processrequest REDEFINITION.
ENDCLASS. "Director DEFINITION
*---*
* CLASS Director IMPLEMENTATION
*---*
*
*---*
CLASS director IMPLEMENTATION.
METHOD processrequest.
FIELD-SYMBOLS:
<fs_amount> TYPE f ,<fs_number> TYPE i.
DATA: class_name TYPE abap_abstypename ,lv_dref TYPE REF TO data.
?get_class_name me class_name.
lv_dref = purchase->get_property( 'AMOUNT' ).
ASSIGN lv_dref->* TO <fs_amount>.
lv_dref = purchase->get_property( 'NUMBER' ).
ASSIGN lv_dref->* TO <fs_number>.
IF <fs_amount> < 10000.
WRITE: / class_name,
me->name, 'Approved request', <fs_number> USING EDIT MASK '____' . ELSE.
IF NOT me->successor IS INITIAL.
me->successor->processrequest( purchase ).
ENDIF.
ENDIF.
ENDMETHOD. "ProcessRequest
ENDCLASS. "Director IMPLEMENTATION
*---*
* CLASS VicePresident DEFINITION
*---*
Project: Design Pattern
*
*---*
CLASS vicepresident DEFINITION INHERITING FROM approver.
PUBLIC SECTION.
METHODS:
processrequest REDEFINITION.
ENDCLASS. "VicePresident DEFINITION
*---*
* CLASS VicePresident IMPLEMENTATION
*---*
*
*---*
CLASS vicepresident IMPLEMENTATION.
METHOD processrequest.
FIELD-SYMBOLS:
<fs_amount> TYPE f ,<fs_number> TYPE i.
DATA: class_name TYPE abap_abstypename ,lv_dref TYPE REF TO data.
?get_class_name me class_name.
lv_dref = purchase->get_property( 'AMOUNT' ).
ASSIGN lv_dref->* TO <fs_amount>.
lv_dref = purchase->get_property( 'NUMBER' ).
ASSIGN lv_dref->* TO <fs_number>.
IF <fs_amount> < 25000.
WRITE: / class_name,
me->name, 'Approved request', <fs_number> USING EDIT MASK '____'.
ELSE.
IF NOT me->successor IS INITIAL.
me->successor->processrequest( purchase ).
ENDIF.
ENDIF.
ENDMETHOD. "ProcessRequest
ENDCLASS. "VicePresident IMPLEMENTATION
*---*
* CLASS President DEFINITION
*---*
*
*---*
CLASS president DEFINITION INHERITING FROM approver.
PUBLIC SECTION.
METHODS:
processrequest REDEFINITION.
ENDCLASS. "President DEFINITION
*---*
* CLASS President IMPLEMENTATION
*---*
*
*---*
CLASS president IMPLEMENTATION.
METHOD processrequest.
FIELD-SYMBOLS:
<fs_amount> TYPE f
Project: Design Pattern
,<fs_number> TYPE i.
DATA: class_name TYPE abap_abstypename ,lv_dref TYPE REF TO data.
?get_class_name me class_name.
lv_dref = purchase->get_property( 'AMOUNT' ).
ASSIGN lv_dref->* TO <fs_amount>.
lv_dref = purchase->get_property( 'NUMBER' ).
ASSIGN lv_dref->* TO <fs_number>.
IF <fs_amount> < 100000.
WRITE: / class_name,
me->name, 'Approved request', <fs_number> USING EDIT MASK '____'.
ELSE.
WRITE: / class_name,
me->name, 'Requires an executive meeting', <fs_number> USING EDIT MASK '____'.
ENDIF.
ENDMETHOD. "ProcessRequest
ENDCLASS. "President IMPLEMENTATION
*---
* CLASS lcl_application DEFINITION
*--- CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.
ENDCLASS. "lcl_application DEFINITION
*---
* IMPLEMENTATION
*--- CLASS lcl_application IMPLEMENTATION.
*---
* LCL_APPLICATION->RUN().
*--- METHOD run.
DATA:
exc_ref TYPE REF TO cx_root ,exc_text TYPE string.
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
*---
* LCL_APPLICATION->CONSTRUCTOR().
Project: Design Pattern
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*--- METHOD constructor.
DATA: larry TYPE REF TO director ,sam TYPE REF TO vicepresident ,tammy TYPE REF TO president ,p TYPE REF TO purchase .
BREAK-POINT.
CREATE OBJECT larry EXPORTING name = 'Larry' . CREATE OBJECT sam EXPORTING name = 'Sam'.
CREATE OBJECT tammy EXPORTING name = 'Tammy'.
larry->setsuccessor( sam ).
sam->setsuccessor( tammy ).
CREATE OBJECT p
EXPORTING number = 2034 amount = 350
purpose = 'Supplies'.
larry->processrequest( p ).
CREATE OBJECT p
EXPORTING number = 2035
amount = '32590.10' purpose = 'Project X'.
larry->processrequest( p ).
CREATE OBJECT p
EXPORTING number = 2036
amount = '122100.00' purpose = 'Project Y'.
larry->processrequest( p ).
ENDMETHOD. "constructor
ENDCLASS. "lcl_application IMPLEMENTATION START-OF-SELECTION.
lcl_application=>run( ).
2.3.2 Command
Encapsulate a command request as an object
2.3.2.1 Definition
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Project: Design Pattern
2.3.2.2 UML class diagram
2.3.2.3 Participants
The classes and/or objects participating in this pattern are:
• Command (Command)
o declares an interface for executing an operation
• ConcreteCommand (CalculatorCommand)
o defines a binding between a Receiver object and an action
o implements Execute by invoking the corresponding operation(s) on Receiver
• Client (CommandApp)
o creates a ConcreteCommand object and sets its receiver
• Invoker (User)
o asks the command to carry out the request
• Receiver (Calculator)
o knows how to perform the operations associated with carrying out the request.