• No results found

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

In document Design Patterns Abap Objects (Page 146-155)

* 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 string

RETURNING 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.

2.3.2.4 Sample code In C#

This structural code demonstrates the Command pattern which stores requests

In document Design Patterns Abap Objects (Page 146-155)