You are on page 1of 224

Design Patterns

Implementation Of objects using design


patterns in Abap Object

Version: 1
Date: 2. Januar 2008
Project: Design Pattern

Version management
Date What has changed Sections Whom Version
01.12.2007 Creation of the document All BGS 1.0

Reference documents
Document Version Location
The Gang Of Four

Participants
Name Company Roll in the project
Benny G. Sørensen BGS
Consulting
ApS

Version: 1.0
Side: ii
Project: Design Pattern

Contents:
1 INTRODUCTION 6
2 DESIGN PATTERNS 6
2.1 CREATIONAL PATTERNS 7
2.1.1 Abstract Factory 7
2.1.1.1 Definition 7
2.1.1.2 Commen Use 8
2.1.1.3 UML class diagram 10
2.1.1.4 Participants 10
2.1.1.5 Sample code in C# 10
2.1.1.6 Sample code in ABAP 13
2.1.1.7 Sample code in C# 16
2.1.1.8 Sample code in ABAP 18
2.1.2 Builder 21
2.1.2.1 Definition 21
2.1.2.2 Useful tips 21
2.1.2.3 UML class diagram 22
2.1.2.4 Participants 22
2.1.2.5 Sample code In C# 22
2.1.2.6 Sample code In ABAP 25
2.1.2.7 Sample code In C# 27
2.1.2.8 Sample code In ABAP 31
2.1.3 Factory Method 34
2.1.3.1 Definition 34
2.1.3.2 UML class diagram 35
2.1.3.3 Participants 35
2.1.3.4 Sample code In C# 35
2.1.3.5 Sample code in ABAP 40
2.1.3.6 Sample code in ABAP 42
2.1.3.7 Sample code in ABAP 44
2.1.4 Prototype 47
2.1.4.1 Definition 47
2.1.4.2 Used for 47
2.1.4.3 UML class diagram 48
2.1.4.4 Participants 48
2.1.4.5 Sample code In C# 48
2.1.4.6 Sample code In ABAP 50
2.1.4.7 Sample code In C# 52
2.1.4.8 Sample code In ABAP 54
2.1.5 Singleton 57
2.1.5.1 Definition 57
2.1.5.2 Common Use 57
2.1.5.3 Implementation 58
2.1.5.4 UML class diagram 59
2.1.5.5 Participants 59
2.1.5.6 Sample code In C# 59
2.1.5.7 Sample code In ABAP 60
2.1.5.8 Sample code In C# 62
2.1.5.9 Sample code In ABAP 64
2.1.5.10 Sample code In ABAP for Application 66
2.2 STRUCTURAL PATTERNS 67
2.2.1 Adapter 67
2.2.1.1 Definition 67
2.2.1.2 Common Use 68
2.2.1.3 UML class diagram 69
2.2.1.4 Participants 69

Version: 1.0
Side: 3
Project: Design Pattern

2.2.1.5 Sample code In C# 69


2.2.1.6 Sample code In ABAP 70
2.2.1.7 Sample code In C# 72
2.2.1.8 Sample code In ABAP 75
2.2.1.9 Sample code In ABAP using interfaces 79
2.2.2 Bridge 83
2.2.2.1 Definition 83
2.2.2.2 Common Use 83
2.2.2.3 UML class diagram 84
2.2.2.4 Participants 84
2.2.2.5 Sample code In C# 84
2.2.3 Composite 84
2.2.3.1 Definition 84
2.2.3.2 UML class diagram 85
2.2.3.3 Participants 85
2.2.3.4 Sample code In C# 85
2.2.3.5 Sample code In ABAP 88
2.2.3.6 Sample code In C# 91
2.2.3.7 Sample code In ABAP 93
2.2.4 Decorator 96
2.2.4.1 Definition 96
2.2.4.2 UML class diagram 97
2.2.4.3 Participants 97
2.2.4.4 Sample code In C# 97
2.2.4.5 Sample code In ABAP 99
2.2.4.6 Sample code In C# 102
2.2.4.7 Sample code In ABAP 105
2.2.5 Facade 110
2.2.5.1 Definition 110
2.2.5.2 UML class diagram 110
2.2.5.3 Participants 110
2.2.5.4 Sample code In C# 111
2.2.5.5 Sample code In ABAP 113
2.2.5.6 Sample code In C# 116
2.2.5.7 Sample code In ABAP 118
2.2.6 Flyweight (fluevægt) 122
2.2.6.1 Definition 122
2.2.6.2 UML class diagram 122
2.2.6.3 Participants 122
2.2.6.4 Sample code In C# 123
2.2.6.5 Sample code In ABAP 124
2.2.6.6 Sample code In C# 127
2.2.7 Proxy 130
2.2.7.1 Definition 130
2.2.7.2 UML class diagram 131
2.2.7.3 Participants 131
2.2.7.4 Sample code In C# 131
2.2.7.5 Sample code In ABAP 133
2.2.7.6 Sample code In C# 135
2.2.7.7 Sample code In ABAP using interface 136
2.3 BEHAVIORAL PATTERNS 139
2.3.1 Chain of Resp. 139
2.3.1.1 Definition 139
2.3.1.2 UML class diagram 140
2.3.1.3 Participants 140
2.3.1.4 Sample code In C# 140
2.3.1.5 Sample code In ABAP 142
2.3.1.6 Sample code In C# 146

Version: 1.0
Side: 4
Project: Design Pattern

2.3.1.7 Sample code In ABAP 149


2.3.2 Command 154
2.3.2.1 Definition 154
2.3.2.2 UML class diagram 155
2.3.2.3 Participants 155
2.3.2.4 Sample code In C# 155
2.3.2.5 Sample code in ABAP 157
2.3.2.6 Sample code In C# 160
2.3.2.7 Sample code In C# 163
2.3.3 Interpreter 169
2.3.3.1 Definition 169
2.3.3.2 UML class diagram 169
2.3.3.3 Participants 169
2.3.3.4 Sample code I C# 170
2.3.4 Iterator 174
2.3.4.1 Definition 174
2.3.4.2 UML class diagram 174
2.3.4.3 Participants 174
2.3.4.4 Sample code I C# 175
2.3.5 Mediator 180
2.3.5.1 Definition 180
2.3.5.2 UML class diagram 181
2.3.5.3 Participants 181
2.3.5.4 Sample code I C# 181
2.3.6 Memento 187
2.3.6.1 Definition 187
2.3.6.2 UML class diagram 187
2.3.6.3 Participants 187
2.3.6.4 Sample code I C# 187
2.3.7 Observer 192
2.3.7.1 Definition 192
2.3.7.2 UML class diagram 193
2.3.7.3 Participants 193
2.3.7.4 Sample code I C# 193
2.3.8 State 198
2.3.8.1 Definition 198
2.3.8.2 UML class diagram 198
2.3.8.3 Participants 199
2.3.8.4 Sample code I C# 199
2.3.9 Strategy 206
2.3.9.1 Definition 206
2.3.9.2 UML class diagram 207
2.3.9.3 Participants 207
2.3.9.4 Sample code In C# 207
2.3.10 Template Method 211
2.3.10.1 Definition 211
2.3.10.2 UML class diagram 212
2.3.10.3 Participants 212
2.3.10.4 Sample code In C# 212
2.3.11 Visitor 216
2.3.11.1 Definition 216
2.3.11.2 UML class diagram 217
2.3.11.3 Participants 217
2.3.11.4 Sample code In C# 218

Version: 1.0
Side: 5
Project: Design Pattern

1 Introduction
2 Design Patterns
Design patterns are recurring solutions to software design problems you find
again and again in real-world application development. Patterns are about
design and interaction of objects, as well as providing a communication
platform concerning elegant, reusable solutions to commonly encountered
programming challenges.

These design patterns have been copied from The Gang of Four homepage.
The Gang of Four (GoF) patterns are generally considered the foundation for all
other patterns. They are categorized in three groups: Creational, Structural,
and Behavioral. Here you will find information on these important patterns.

To give you a head start, the C# source code is provided in 2 forms:


'structural' and 'real-world'.

Structural code uses type names as defined in the pattern definition and UML
diagrams.

Real-world code provides real-world programming situations where you may


use these patterns.

A third form, 'ABAP Object' demonstrates design patterns that exploit SAP R/3
built-in ABAP Object’s features.

Creational Patterns

Abstract Factory Creates an instance of several families of classes

Builder Separates object construction from its representation

Factory Method Creates an instance of several derived classes

Prototype A fully initialized instance to be copied or cloned

Singleton A class of which only a single instance can exist

Structural Patterns

Adapter Match interfaces of different classes

Bridge Separates an object’s interface from its implementation

Composite A tree structure of simple and composite objects

Decorator Add responsibilities to objects dynamically

Facade A single class that represents an entire subsystem

Version: 1.0
Side: 6
Project: Design Pattern

Flyweight A fine-grained instance used for efficient sharing

Proxy An object representing another object

Behavioral Patterns

Chain of Resp. A way of passing a request between a chain of objects

Command Encapsulate a command request as an object

Interpreter A way to include language elements in a program

Iterator Sequentially access the elements of a collection

Mediator Defines simplified communication between classes

Memento Capture and restore an object's internal state

Observer A way of notifying change to a number of classes

State Alter an object's behavior when its state changes

Strategy Encapsulates an algorithm inside a class

Template Method Defer the exact steps of an algorithm to a subclass

Visitor Defines a new operation to a class without change

2.1 Creational Patterns


2.1.1 Abstract Factory
Creates an instance of several families of classes

2.1.1.1 Definition
Provide an interface for creating families of related or dependent objects
without specifying their concrete classes

A software design pattern, the Abstract Factory Pattern provides a way to


encapsulate a group of individual factories that have a common theme. In
normal usage, the client software would create a concrete implementation of
the abstract factory and then use the generic interfaces to create the concrete
objects that are part of the theme.

The client does not know (nor care) about which concrete objects it gets from
each of these internal factories since it uses only the generic interfaces of their
products. This pattern separates the details of implementation of a set of
objects from its general usage.

Version: 1.0
Side: 7
Project: Design Pattern

An example of this would be an abstract factory class DocumentCreator that


provides interfaces to create a number of products (eg. createLetter() and
createResume()).

The system would have any number of derived concrete versions of the
DocumentCreator class like FancyDocumentCreator or
ModernDocumentCreator, each with a different implementation of
createLetter() and createResume() that would create a corresponding object
like FancyLetter or ModernResume. Each of these products is derived from a
simple abstract class like Letter or Resume of which the client is aware. The
client code would get an appropriate instantiation of the DocumentCreator and
call its factory methods. Each of the resulting objects would be created from
the same DocumentCreator implementation and would share a common theme
(they would all be fancy or modern objects). The client would need to know
how to handle only the abstract Letter or Resume class, not the specific
version that it got from the concrete factory.

In software development, a Factory is the location in the code at which


objects are constructed. The intent in employing the pattern is to insulate the
creation of objects from their usage. This allows for new derived types to be
introduced with no change to the code that uses the base class.
Use of this pattern makes it possible to interchange concrete classes without
changing the code that uses them, even at runtime. However, employment of
this pattern, as with similar design patterns, incurs the risk of unnecessary
complexity and extra work in the initial writing of code.

2.1.1.2 Commen Use

The factory determines the actual concrete type of object to be created, and it
is here that the object is actually created (in C++, for instance, by the new
operator). However, the factory only returns an abstract pointer to the created
concrete object.

This insulates client code from object creation by having clients ask a factory
object to create an object of the desired abstract type and to return an
abstract pointer to the object.

As the factory only returns an abstract pointer, the client code (which
requested the object from the factory) does not know - and is not burdened by
- the actual concrete type of the object which was just created. However, the
type of a concrete object (and hence a concrete factory) is known by the
abstract factory; for instance, the factory may read it from a configuration file.
The client has no need to specify the type, since it has already been specified
in the configuration file. In particular, this means:

Version: 1.0
Side: 8
Project: Design Pattern

• The client code has no knowledge whatsoever of the concrete type, not
needing to include any header files or class declarations relating to the
concrete type. The client code deals only with the abstract type. Objects
of a concrete type are indeed created by the factory, but the client code
accesses such objects only through their abstract interface.

• Adding new concrete types is done by modifying the client code to use a
different factory, a modification which is typically one line in one file.
(The different factory then creates objects of a different concrete type,
but still returns a pointer of the same abstract type as before - thus
insulating the client code from change.) This is significantly easier than
modifying the client code to instantiate a new type, which would require
changing every location in the code where a new object is created (as
well as making sure that all such code locations also have knowledge of
the new concrete type, by including for instance a concrete class header
file). If all factory objects are stored globally in a singleton object, and all
client code goes through the singleton to access the proper factory for
object creation, then changing factories is as easy as changing the
singleton object.

The class diagram of this design pattern is as shown

Version: 1.0
Side: 9
Project: Design Pattern

2.1.1.3 UML class diagram

2.1.1.4 Participants
The classes and/or objects participating in this pattern are:
• AbstractFactory (ContinentFactory)
declares an interface for operations that create abstract products
• ConcreteFactory (AfricaFactory, AmericaFactory)
implements the operations to create concrete product objects
• AbstractProduct (Herbivore, Carnivore)
declares an interface for a type of product object
• Product (Wildebeest, Lion, Bison, Wolf)
defines a product object to be created by the corresponding concrete
factory implements the AbstractProduct interface
• Client (AnimalWorld)
uses interfaces declared by AbstractFactory and AbstractProduct classes

2.1.1.5 Sample code in C#


This structural code demonstrates the Abstract Factory pattern creating
parallel hierarchies of objects. Object creation has been abstracted and there is
no need for hard-coded class names in the client code.

// Abstract Factory pattern -- Structural example

Version: 1.0
Side: 10
Project: Design Pattern

using System;

namespace DoFactory.GangOfFour.Abstract.Structural
{
// MainApp test application

class MainApp
{
public static void Main()
{
// Abstract factory #1
AbstractFactory factory1 = new ConcreteFactory1();
Client c1 = new Client(factory1);
c1.Run();

// Abstract factory #2
AbstractFactory factory2 = new ConcreteFactory2();
Client c2 = new Client(factory2);
c2.Run();

// Wait for user input


Console.Read();
}
}

// "AbstractFactory"

abstract class AbstractFactory


{
public abstract AbstractProductA CreateProductA();
public abstract AbstractProductB CreateProductB();
}

// "ConcreteFactory1"

class ConcreteFactory1 : AbstractFactory


{
public override AbstractProductA CreateProductA()
{
return new ProductA1();
}
public override AbstractProductB CreateProductB()
{
return new ProductB1();
}
}

// "ConcreteFactory2"

class ConcreteFactory2 : AbstractFactory


{
public override AbstractProductA CreateProductA()
{
return new ProductA2();
}
public override AbstractProductB CreateProductB()

Version: 1.0
Side: 11
Project: Design Pattern

{
return new ProductB2();
}
}

// "AbstractProductA"

abstract class AbstractProductA


{
}

// "AbstractProductB"

abstract class AbstractProductB


{
public abstract void Interact(AbstractProductA a);
}

// "ProductA1"

class ProductA1 : AbstractProductA


{
}

// "ProductB1"

class ProductB1 : AbstractProductB


{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name +
" interacts with " + a.GetType().Name);
}
}

// "ProductA2"

class ProductA2 : AbstractProductA


{
}

// "ProductB2"

class ProductB2 : AbstractProductB


{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name +
" interacts with " + a.GetType().Name);
}
}

// "Client" - the interaction environment of the products

class Client
{

Version: 1.0
Side: 12
Project: Design Pattern

private AbstractProductA AbstractProductA;


private AbstractProductB AbstractProductB;

// Constructor
public Client(AbstractFactory factory)
{
AbstractProductB = factory.CreateProductB();
AbstractProductA = factory.CreateProductA();
}

public void Run()


{
AbstractProductB.Interact(AbstractProductA);
}
}
}

Output
ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2

2.1.1.6 Sample code in ABAP


This structural code demonstrates the Abstract Factory pattern creating
parallel hierarchies of objects. Object creation has been abstracted and there is
no need for hard-coded class names in the client code. In ABAP you should
consider using interfaces instead of abstract classes.

REPORT ZABSTRACTFACTORY_STRUCTURAL NO STANDARD PAGE HEADING LINE-SIZE 80.


CLASS cl_abap_typedescr DEFINITION LOAD.

DATA: moff TYPE i


,slen TYPE i
,mlen TYPE i.

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 abstractproducta DEFINITION ABSTRACT.


ENDCLASS. "abstractproducta DEFINITION

CLASS abstractproductb DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
interact ABSTRACT IMPORTING a TYPE REF TO abstractproducta .
ENDCLASS. "abstractproductb DEFINITION

CLASS abstractproductb IMPLEMENTATION.


ENDCLASS. "abstractproductb IMPLEMENTATION

CLASS producta1 DEFINITION INHERITING FROM abstractproducta.


ENDCLASS. "producta1 DEFINITION

CLASS productb1 DEFINITION INHERITING FROM abstractproductb.

Version: 1.0
Side: 13
Project: Design Pattern

PUBLIC SECTION.
METHODS:
interact REDEFINITION.
ENDCLASS. "productb1 DEFINITION

CLASS productb1 IMPLEMENTATION.


METHOD interact.
DATA: class_name_me TYPE abap_abstypename
,class_name_a TYPE abap_abstypename.
?get_class_name me class_name_me.
?get_class_name a class_name_a.
WRITE: / class_name_me
,'Interact with '
,class_name_a.
ENDMETHOD. "interact
ENDCLASS. "productb1 IMPLEMENTATION

CLASS producta2 DEFINITION INHERITING FROM abstractproducta.


ENDCLASS. "producta2 DEFINITION

CLASS productb2 DEFINITION INHERITING FROM abstractproductb.


PUBLIC SECTION.
METHODS:
interact REDEFINITION.
ENDCLASS. "productb2 DEFINITION

CLASS productb2 IMPLEMENTATION.


METHOD interact.
DATA: class_name_me TYPE abap_abstypename
,class_name_a TYPE abap_abstypename.
?get_class_name me class_name_me.
?get_class_name a class_name_a.
WRITE: / class_name_me
,'Interact with '
,class_name_a.
ENDMETHOD. "interact
ENDCLASS. "productb2 IMPLEMENTATION

CLASS abstractfactory DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
createproducta ABSTRACT RETURNING value(producta) TYPE REF TO abstractproducta
,createproductb ABSTRACT RETURNING value(productb) TYPE REF TO abstractproductb
.
ENDCLASS. "abstractfactory DEFINITION

CLASS concretefactory1 DEFINITION INHERITING FROM abstractfactory.


PUBLIC SECTION.
METHODS:
createproducta REDEFINITION
,createproductb REDEFINITION
.
ENDCLASS. "concretefactory1 DEFINITION

CLASS concretefactory1 IMPLEMENTATION.


METHOD createproducta.
CREATE OBJECT producta TYPE producta1.
ENDMETHOD. "createproducta

METHOD createproductb.
CREATE OBJECT productb TYPE productb1.
ENDMETHOD. "createproductb
ENDCLASS. "concretefactory1 IMPLEMENTATION

CLASS concretefactory2 DEFINITION INHERITING FROM abstractfactory.


PUBLIC SECTION.

Version: 1.0
Side: 14
Project: Design Pattern

METHODS:
createproducta REDEFINITION
,createproductb REDEFINITION
.
ENDCLASS. "concretefactory2 DEFINITION

CLASS concretefactory2 IMPLEMENTATION.


METHOD createproducta.
CREATE OBJECT producta TYPE producta2.
ENDMETHOD. "createproducta

METHOD createproductb.
CREATE OBJECT productb TYPE productb2.
ENDMETHOD. "createproductb
ENDCLASS. "concretefactory1 IMPLEMENTATION

CLASS client DEFINITION.


PUBLIC SECTION.
METHODS:
constructor IMPORTING factory TYPE REF TO abstractfactory
,run
.
PROTECTED SECTION.
DATA: abstractproducta TYPE REF TO abstractproducta
,abstractproductb TYPE REF TO abstractproductb
.
ENDCLASS. "client DEFINITION

CLASS client IMPLEMENTATION.


METHOD constructor.
abstractproducta = factory->createproducta( ).
abstractproductb = factory->createproductb( ).
ENDMETHOD. "constructor
METHOD run.
abstractproductb->interact( abstractproducta ).
ENDMETHOD. "run
ENDCLASS. "client IMPLEMENTATION

CLASS mainapp DEFINITION.


PUBLIC SECTION.
* CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator.
CLASS-METHODS main.
ENDCLASS. "mainapp DEFINITION

CLASS mainapp IMPLEMENTATION.


METHOD main.
DATA: factory1 TYPE REF TO concretefactory1
,factory2 TYPE REF TO concretefactory2
,c1 TYPE REF TO client
,c2 TYPE REF TO client
.

CREATE OBJECT factory1.


CREATE OBJECT c1 EXPORTING factory = factory1 .
CALL METHOD c1->run( ).

CREATE OBJECT factory2.


CREATE OBJECT c2 EXPORTING factory = factory2.

CALL METHOD c2->run( ).

ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Version: 1.0
Side: 15
Project: Design Pattern

Output
PRODUCTB1
Interact with
PRODUCTA1
PRODUCTB2
Interact with
PRODUCTA2

2.1.1.7 Sample code in C#


This real-world code demonstrates the creation of different animal worlds for a
computer game using different factories. Although the animals created by the
Continent factories are different, the interactions among the animals remain
the same.
// Abstract Factory pattern -- Real World example

using System;

namespace DoFactory.GangOfFour.Abstract.RealWorld
{
// MainApp test application

class MainApp
{
public static void Main()
{
// Create and run the Africa animal world
ContinentFactory africa = new AfricaFactory();
AnimalWorld world = new AnimalWorld(africa);
world.RunFoodChain();

// Create and run the America animal world


ContinentFactory america = new AmericaFactory();
world = new AnimalWorld(america);
world.RunFoodChain();

// Wait for user input


Console.Read();
}
}

// "AbstractFactory"

abstract class ContinentFactory


{
public abstract Herbivore CreateHerbivore();
public abstract Carnivore CreateCarnivore();
}

// "ConcreteFactory1"

class AfricaFactory : ContinentFactory


{
public override Herbivore CreateHerbivore()
{

Version: 1.0
Side: 16
Project: Design Pattern

return new Wildebeest();


}
public override Carnivore CreateCarnivore()
{
return new Lion();
}
}

// "ConcreteFactory2"

class AmericaFactory : ContinentFactory


{
public override Herbivore CreateHerbivore()
{
return new Bison();
}
public override Carnivore CreateCarnivore()
{
return new Wolf();
}
}

// "AbstractProductA"

abstract class Herbivore


{
}

// "AbstractProductB"

abstract class Carnivore


{
public abstract void Eat(Herbivore h);
}

// "ProductA1"

class Wildebeest : Herbivore


{
}

// "ProductB1"

class Lion : Carnivore


{
public override void Eat(Herbivore h)
{
// Eat Wildebeest
Console.WriteLine(this.GetType().Name +
" eats " + h.GetType().Name);
}
}

// "ProductA2"

class Bison : Herbivore

Version: 1.0
Side: 17
Project: Design Pattern

{
}

// "ProductB2"

class Wolf : Carnivore


{
public override void Eat(Herbivore h)
{
// Eat Bison
Console.WriteLine(this.GetType().Name +
" eats " + h.GetType().Name);
}
}

// "Client"

class AnimalWorld
{
private Herbivore herbivore;
private Carnivore carnivore;

// Constructor
public AnimalWorld(ContinentFactory factory)
{
carnivore = factory.CreateCarnivore();
herbivore = factory.CreateHerbivore();
}

public void RunFoodChain()


{
carnivore.Eat(herbivore);
}
}
}

Output
Lion eats Wildebeest
Wolf eats Bison

2.1.1.8 Sample code in ABAP


This real-world code demonstrates the creation of different animal worlds for a
computer game using different factories. Although the animals created by the
Continent factories are different, the interactions among the animals remain
the same. You should however consider using interfaces instead of abstract
classes.
REPORT zabstractfactory_realworld NO STANDARD PAGE HEADING LINE-SIZE 80.
CLASS cl_abap_typedescr DEFINITION LOAD.

DATA: moff TYPE i


,slen TYPE i
,mlen TYPE i.

DEFINE ?get_class_name.

Version: 1.0
Side: 18
Project: Design Pattern

&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 herbivore DEFINITION ABSTRACT.


ENDCLASS. "herbivore DEFINITION

CLASS carnivore DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
eat ABSTRACT IMPORTING a TYPE REF TO herbivore .
ENDCLASS. "carnivore DEFINITION

CLASS carnivore IMPLEMENTATION.


ENDCLASS. "carnivore IMPLEMENTATION

CLASS wildebeest DEFINITION INHERITING FROM herbivore.


ENDCLASS. "wildebeest DEFINITION

CLASS lion DEFINITION INHERITING FROM carnivore.


PUBLIC SECTION.
METHODS:
eat REDEFINITION.
ENDCLASS. "Lion DEFINITION

CLASS lion IMPLEMENTATION.


METHOD eat.
DATA: class_name_me TYPE abap_abstypename
,class_name_a TYPE abap_abstypename.
?get_class_name me class_name_me.
?get_class_name a class_name_a.
WRITE: / class_name_me
,' eats '
,class_name_a.
ENDMETHOD. "interact
ENDCLASS. "Lion IMPLEMENTATION

CLASS bison DEFINITION INHERITING FROM herbivore.


ENDCLASS. "Bison DEFINITION

CLASS wolf DEFINITION INHERITING FROM carnivore.


PUBLIC SECTION.
METHODS:
eat REDEFINITION.
ENDCLASS. "Wolf DEFINITION

CLASS wolf IMPLEMENTATION.


METHOD eat.
DATA: class_name_me TYPE abap_abstypename
,class_name_a TYPE abap_abstypename.
?get_class_name me class_name_me.
?get_class_name a class_name_a.
WRITE: / class_name_me
,' eats '
,class_name_a.
ENDMETHOD. "interact
ENDCLASS. "Wolf IMPLEMENTATION

CLASS continentfactory DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
createherbivore ABSTRACT RETURNING value(herbivore) TYPE REF TO herbivore
,createcarnivore ABSTRACT RETURNING value(carnivore) TYPE REF TO carnivore
.

Version: 1.0
Side: 19
Project: Design Pattern

ENDCLASS. "ContinentFactory DEFINITION

CLASS africafactory DEFINITION INHERITING FROM continentfactory.


PUBLIC SECTION.
METHODS:
createherbivore REDEFINITION
,createcarnivore REDEFINITION
.
ENDCLASS. "ContinentFactory DEFINITION

CLASS africafactory IMPLEMENTATION.


METHOD createherbivore.
CREATE OBJECT herbivore TYPE wildebeest.
ENDMETHOD. "createproducta

METHOD createcarnivore.
CREATE OBJECT carnivore TYPE lion.
ENDMETHOD. "createproductb
ENDCLASS. "ContinentFactory IMPLEMENTATION

CLASS americafactory DEFINITION INHERITING FROM continentfactory.


PUBLIC SECTION.
METHODS:
createherbivore REDEFINITION
,createcarnivore REDEFINITION
.
ENDCLASS. "concretefactory2 DEFINITION

CLASS americafactory IMPLEMENTATION.


METHOD createherbivore.
CREATE OBJECT herbivore TYPE bison.
ENDMETHOD. "createproducta

METHOD createcarnivore.
CREATE OBJECT carnivore TYPE wolf.
ENDMETHOD. "createproductb
ENDCLASS. "ContinentFactory IMPLEMENTATION

CLASS animalworld DEFINITION.


PUBLIC SECTION.
METHODS:
constructor IMPORTING factory TYPE REF TO continentfactory
,runfoodchain
.
PROTECTED SECTION.
DATA: herbivore TYPE REF TO herbivore
,carnivore TYPE REF TO carnivore
.
ENDCLASS. "Animalworld DEFINITION

CLASS animalworld IMPLEMENTATION.


METHOD constructor.
herbivore = factory->createherbivore( ).
carnivore = factory->createcarnivore( ).
ENDMETHOD. "constructor
METHOD runfoodchain.
carnivore->eat( herbivore ).
ENDMETHOD. "Runfoodchain
ENDCLASS. "Animalworld IMPLEMENTATION

CLASS mainapp DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "mainapp DEFINITION

Version: 1.0
Side: 20
Project: Design Pattern

CLASS mainapp IMPLEMENTATION.


METHOD main.
DATA: africa TYPE REF TO africafactory
,america TYPE REF TO americafactory
,world TYPE REF TO animalworld
.

CREATE OBJECT africa.


CREATE OBJECT world EXPORTING factory = africa .
CALL METHOD world->runfoodchain( ).

CREATE OBJECT america.


CREATE OBJECT world EXPORTING factory = america.
CALL METHOD world->runfoodchain( ).

ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Output
LION
eats
WILDEBEEST
WOLF
eats
BISON

2.1.2 Builder
Separates object construction from its representation

2.1.2.1 Definition
Separate the construction of a complex object from its representation so that
the same construction process can create different representations.

The Builder Pattern is a software design pattern. The intention is to separate


the construction of a complex object from its representation so that the same
construction process can create different representations.
Often, Builder Pattern builds Composite pattern, a structure pattern.

2.1.2.2 Useful tips


• Sometimes creational patterns are complementary: Builder can use one
of the other patterns to implement which components get built. Abstract
Factory, Builder, and Prototype can use Singleton in their
implementations.

• Builder focuses on constructing a complex object step by step. Abstract


Factory emphasizes a family of product objects (either simple or
complex). Builder returns the product as a final step, but as far as the

Version: 1.0
Side: 21
Project: Design Pattern

Abstract Factory is concerned, the product gets returned immediately.

• Builder often builds a Composite.

• Often, designs start out using Factory Method (less complicated, more
customizable, subclasses proliferate) and evolve toward Abstract Factory,
Prototype, or Builder (more flexible, more complex) as the designer
discovers where more flexibility is needed.

2.1.2.3 UML class diagram

2.1.2.4 Participants
The classes and/or objects participating in this pattern are:
• Builder (VehicleBuilder)
o specifies an abstract interface for creating parts of a Product object
• ConcreteBuilder (MotorCycleBuilder, CarBuilder, ScooterBuilder)
o constructs and assembles parts of the product by implementing the
Builder interface defines and keeps track of the representation it
creates provides an interface for retrieving the product
• Director (Shop)
o constructs an object using the Builder interface
• Product (Vehicle)
o represents the complex object under construction. ConcreteBuilder
builds the product's internal representation and defines the process
by which it's assembled includes classes that define the constituent
parts, including interfaces for assembling the parts into the final
result

2.1.2.5 Sample code In C#


This structural code demonstrates the Builder pattern in which complex objects
are created in a step-by-step fashion. The construction process can create
different object representations and provides a high level of control over the
assembly of the objects.

// Builder pattern -- Structural example

Version: 1.0
Side: 22
Project: Design Pattern

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Builder.Structural
{
// MainApp test application

public class MainApp


{
public static void Main()
{
// Create director and builders
Director director = new Director();

Builder b1 = new ConcreteBuilder1();


Builder b2 = new ConcreteBuilder2();

// Construct two products


director.Construct(b1);
Product p1 = b1.GetResult();
p1.Show();

director.Construct(b2);
Product p2 = b2.GetResult();
p2.Show();

// Wait for user


Console.Read();
}
}

// "Director"

class Director
{
// Builder uses a complex series of steps
public void Construct(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
}

// "Builder"

abstract class Builder


{
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract Product GetResult();
}

// "ConcreteBuilder1"

class ConcreteBuilder1 : Builder

Version: 1.0
Side: 23
Project: Design Pattern

{
private Product product = new Product();

public override void BuildPartA()


{
product.Add("PartA");
}

public override void BuildPartB()


{
product.Add("PartB");
}

public override Product GetResult()


{
return product;
}
}

// "ConcreteBuilder2"

class ConcreteBuilder2 : Builder


{
private Product product = new Product();

public override void BuildPartA()


{
product.Add("PartX");
}

public override void BuildPartB()


{
product.Add("PartY");
}

public override Product GetResult()


{
return product;
}
}

// "Product"

class Product
{
ArrayList parts = new ArrayList();

public void Add(string part)


{
parts.Add(part);
}

public void Show()


{
Console.WriteLine("\nProduct Parts -------");
foreach (string part in parts)

Version: 1.0
Side: 24
Project: Design Pattern

Console.WriteLine(part);
}
}
}

Output
Product Parts -------
PartA
PartB

Product Parts -------


PartX
PartY

2.1.2.6 Sample code In ABAP


This structural code demonstrates the Builder pattern in which complex objects
are created in a step-by-step fashion. The construction process can create
different object representations and provides a high level of control over the
assembly of the objects.
REPORT zbuilder_structural NO STANDARD PAGE HEADING LINE-SIZE 80.

CLASS product DEFINITION.


PUBLIC SECTION.
DATA: parts TYPE TABLE OF string.
METHODS:
add IMPORTING part TYPE string
,show.
ENDCLASS. "product DEFINITION

CLASS product IMPLEMENTATION.


METHOD add.
APPEND part TO parts.
ENDMETHOD. "add

METHOD show.
DATA: parts_line TYPE string.
WRITE: / 'Product Parts --------'.
LOOP AT parts INTO parts_line.
WRITE: / parts_line.
ENDLOOP.
ENDMETHOD. "show
ENDCLASS. "product IMPLEMENTATION

CLASS builder DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
buildparta ABSTRACT
,buildpartb ABSTRACT
,getresult ABSTRACT RETURNING value(product) TYPE REF TO product.
ENDCLASS. "builder DEFINITION

CLASS concretebuilder1 DEFINITION INHERITING FROM builder.


PUBLIC SECTION.
METHODS:
constructor
,buildparta REDEFINITION
,buildpartb REDEFINITION
,getresult REDEFINITION

Version: 1.0
Side: 25
Project: Design Pattern

.
PRIVATE SECTION.
DATA: product TYPE REF TO product.
ENDCLASS. "concretebuilder1 DEFINITION

CLASS concretebuilder1 IMPLEMENTATION.


METHOD constructor.
CALL METHOD super->constructor.
CREATE OBJECT me->product.
ENDMETHOD. "constructor
METHOD buildparta.
product->add('PartA').
ENDMETHOD. "buildparta
METHOD buildpartb.
product->add('Partb').
ENDMETHOD. "buildpartb
METHOD getresult.
product = me->product.
ENDMETHOD. "getresult
ENDCLASS. "concretebuilder1 IMPLEMENTATION

CLASS concretebuilder2 DEFINITION INHERITING FROM builder.


PUBLIC SECTION.
METHODS:
constructor
,buildparta REDEFINITION
,buildpartb REDEFINITION
,getresult REDEFINITION
.
PRIVATE SECTION.
DATA: product TYPE REF TO product.
ENDCLASS. "concretebuilder2 DEFINITION

CLASS concretebuilder2 IMPLEMENTATION.


METHOD constructor.
CALL METHOD super->constructor.
CREATE OBJECT me->product.
ENDMETHOD. "constructor
METHOD buildparta.
product->add('PartX').
ENDMETHOD. "buildparta
METHOD buildpartb.
product->add('PartY').
ENDMETHOD. "buildpartb
METHOD getresult.
product = me->product.
ENDMETHOD. "getresult
ENDCLASS. "concretebuilder2 IMPLEMENTATION

CLASS director DEFINITION.


PUBLIC SECTION.
METHODS:
construct IMPORTING builder TYPE REF TO builder.
ENDCLASS. "director DEFINITION

CLASS director IMPLEMENTATION.


METHOD construct.
builder->buildparta( ).
builder->buildpartb( ).
ENDMETHOD. "construct
ENDCLASS. "director IMPLEMENTATION

CLASS mainapp DEFINITION.


PUBLIC SECTION.
CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator.
CLASS-METHODS main.

Version: 1.0
Side: 26
Project: Design Pattern

ENDCLASS. "mainapp DEFINITION

CLASS mainapp IMPLEMENTATION.


METHOD main.
DATA: director TYPE REF TO director
,b1 TYPE REF TO concretebuilder1
,b2 TYPE REF TO concretebuilder2
,p1 TYPE REF TO product
,p2 TYPE REF TO product
.
FIELD-SYMBOLS <fs> TYPE ANY.

CREATE OBJECT director.


CREATE OBJECT b1.
CALL METHOD director->construct( b1 ).
p1 = b1->getresult( ).
p1->show( ).

CREATE OBJECT b2.


CALL METHOD director->construct( b2 ).
p2 = b2->getresult( ).
p2->show( ).

ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Output
Product Parts
PartA
Partb
Product Parts
PartX
PartY

2.1.2.7 Sample code In C#

This real-world code demonstates the Builder pattern in which different


vehicles are assembled in a step-by-step fashion. The Shop uses
VehicleBuilders to construct a variety of Vehicles in a series of sequential
steps.

// Builder pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Builder.RealWorld
{
// MainApp test application

public class MainApp


{
public static void Main()
{
// Create shop with vehicle builders
Shop shop = new Shop();

Version: 1.0
Side: 27
Project: Design Pattern

VehicleBuilder b1 = new ScooterBuilder();


VehicleBuilder b2 = new CarBuilder();
VehicleBuilder b3 = new MotorCycleBuilder();

// Construct and display vehicles


shop.Construct(b1);
b1.Vehicle.Show();

shop.Construct(b2);
b2.Vehicle.Show();

shop.Construct(b3);
b3.Vehicle.Show();

// Wait for user


Console.Read();
}
}

// "Director"

class Shop
{
// Builder uses a complex series of steps
public void Construct(VehicleBuilder vehicleBuilder)
{
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWheels();
vehicleBuilder.BuildDoors();
}
}

// "Builder"

abstract class VehicleBuilder


{
protected Vehicle vehicle;

// Property
public Vehicle Vehicle
{
get{ return vehicle; }
}

public abstract void BuildFrame();


public abstract void BuildEngine();
public abstract void BuildWheels();
public abstract void BuildDoors();
}

// "ConcreteBuilder1"

class MotorCycleBuilder : VehicleBuilder


{
public override void BuildFrame()

Version: 1.0
Side: 28
Project: Design Pattern

{
vehicle = new Vehicle("MotorCycle");
vehicle["frame"] = "MotorCycle Frame";
}

public override void BuildEngine()


{
vehicle["engine"] = "500 cc";
}

public override void BuildWheels()


{
vehicle["wheels"] = "2";
}

public override void BuildDoors()


{
vehicle["doors"] = "0";
}
}

// "ConcreteBuilder2"

class CarBuilder : VehicleBuilder


{
public override void BuildFrame()
{
vehicle = new Vehicle("Car");
vehicle["frame"] = "Car Frame";
}

public override void BuildEngine()


{
vehicle["engine"] = "2500 cc";
}

public override void BuildWheels()


{
vehicle["wheels"] = "4";
}

public override void BuildDoors()


{
vehicle["doors"] = "4";
}
}

// "ConcreteBuilder3"

class ScooterBuilder : VehicleBuilder


{
public override void BuildFrame()
{
vehicle = new Vehicle("Scooter");
vehicle["frame"] = "Scooter Frame";
}

Version: 1.0
Side: 29
Project: Design Pattern

public override void BuildEngine()


{
vehicle["engine"] = "50 cc";
}

public override void BuildWheels()


{
vehicle["wheels"] = "2";
}

public override void BuildDoors()


{
vehicle["doors"] = "0";
}
}

// "Product"

class Vehicle
{
private string type;
private Hashtable parts = new Hashtable();

// Constructor
public Vehicle(string type)
{
this.type = type;
}

// Indexer (i.e. smart array)


public object this[string key]
{
get{ return parts[key]; }
set{ parts[key] = value; }
}

public void Show()


{
Console.WriteLine("\n---------------------------");
Console.WriteLine("Vehicle Type: {0}", type);
Console.WriteLine(" Frame : {0}", parts["frame"]);
Console.WriteLine(" Engine : {0}", parts["engine"]);
Console.WriteLine(" #Wheels: {0}", parts["wheels"]);
Console.WriteLine(" #Doors : {0}", parts["doors"]);
}
}
}

Output
---------------------------
Vehicle Type: Scooter
Frame : Scooter Frame
Engine : none
#Wheels: 2
#Doors : 0

Version: 1.0
Side: 30
Project: Design Pattern

---------------------------
Vehicle Type: Car
Frame : Car Frame
Engine : 2500 cc
#Wheels: 4
#Doors : 4

---------------------------
Vehicle Type: MotorCycle
Frame : MotorCycle Frame
Engine : 500 cc
#Wheels: 2
#Doors : 0

2.1.2.8 Sample code In ABAP

This real-world code demonstates the Builder pattern in which different


vehicles are assembled in a step-by-step fashion. The Shop uses
VehicleBuilders to construct a variety of Vehicles in a series of sequential
steps.

REPORT zbuilder_realworld NO STANDARD PAGE HEADING LINE-SIZE 80.

CLASS vehicle DEFINITION.


PUBLIC SECTION.
TYPES: ty_key(30) TYPE c
,ty_part(30) TYPE c
,BEGIN OF ty_parts
,key TYPE ty_key
,part TYPE ty_part
,END OF ty_parts.
METHODS:
constructor IMPORTING vtype TYPE string
,add IMPORTING key TYPE ty_key
part TYPE ty_part
,show.
PRIVATE SECTION.
DATA: parts TYPE HASHED TABLE OF ty_parts
WITH UNIQUE KEY key
,vtype(30) TYPE c.
ENDCLASS. "Vehicle DEFINITION

CLASS vehicle IMPLEMENTATION.


METHOD constructor.
me->vtype = vtype.
ENDMETHOD. "constructor
METHOD add.
DATA: buffer TYPE ty_parts.
buffer-key = key.
buffer-part = part.

INSERT buffer INTO TABLE parts.


ENDMETHOD. "add

METHOD show.
DATA: parts_line TYPE ty_parts.
write: / '---------------------------------------------'.
WRITE: / 'Vehicle Type:' , vtype.
LOOP AT parts INTO parts_line.
WRITE: / parts_line-key, parts_line-part.
ENDLOOP.

Version: 1.0
Side: 31
Project: Design Pattern

ENDMETHOD. "show
ENDCLASS. "Vehicle IMPLEMENTATION

CLASS vehiclebuilder DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
constructor IMPORTING vtype TYPE string
,buildframe ABSTRACT
,buildengine ABSTRACT
,buildwheels ABSTRACT
,builddoors ABSTRACT
,getvehicle RETURNING value(vehicle) TYPE REF TO vehicle
,show.
PROTECTED SECTION.
DATA: vehicle TYPE REF TO vehicle.
ENDCLASS. "builder DEFINITION

CLASS vehiclebuilder IMPLEMENTATION.


METHOD constructor.
CREATE OBJECT vehicle EXPORTING vtype = vtype.
ENDMETHOD. "constructor

METHOD getvehicle.
vehicle = me->vehicle.
ENDMETHOD. "vehicle
METHOD show.
vehicle->show( ).
ENDMETHOD. "show
ENDCLASS. "vehiclebuilder IMPLEMENTATION

CLASS motorcyclebuilder DEFINITION INHERITING FROM vehiclebuilder.


PUBLIC SECTION.
METHODS:
buildframe REDEFINITION
,buildengine REDEFINITION
,buildwheels REDEFINITION
,builddoors REDEFINITION
.
ENDCLASS. "Motorcycle DEFINITION

CLASS motorcyclebuilder IMPLEMENTATION.


METHOD buildframe.
CREATE OBJECT vehicle EXPORTING vtype = 'MotorCycle'.
vehicle->add( EXPORTING key = 'frame'
part = 'Motorcycle Frame' ).
ENDMETHOD. "buildparta
METHOD buildengine.
vehicle->add( EXPORTING key = 'engine'
part = '500 cc' ).
ENDMETHOD. "buildpartb
METHOD buildwheels.
vehicle->add( EXPORTING key = 'wheels'
part = '2' ) .
ENDMETHOD. "buildwheels
METHOD builddoors.
vehicle->add( EXPORTING key = 'doors'
part = '0' ) .
ENDMETHOD. "builddoors
ENDCLASS. "Motorcycle IMPLEMENTATION

CLASS carbuilder DEFINITION INHERITING FROM vehiclebuilder.


PUBLIC SECTION.
METHODS:
buildframe REDEFINITION
,buildengine REDEFINITION
,buildwheels REDEFINITION

Version: 1.0
Side: 32
Project: Design Pattern

,builddoors REDEFINITION
.
ENDCLASS. "Carbuilder DEFINITION

CLASS carbuilder IMPLEMENTATION.


METHOD buildframe.
CREATE OBJECT vehicle EXPORTING vtype = 'Car'.
vehicle->add( EXPORTING key = 'frame'
part = 'Car Frame' ).
ENDMETHOD. "buildparta
METHOD buildengine.
vehicle->add( EXPORTING key = 'engine'
part = '2500 cc' ).
ENDMETHOD. "buildpartb
METHOD buildwheels.
vehicle->add( EXPORTING key = 'wheels'
part = '4' ) .
ENDMETHOD. "buildwheels
METHOD builddoors.
vehicle->add( EXPORTING key = 'doors'
part = '4' ) .
ENDMETHOD. "builddoors

ENDCLASS. "Carbuilder IMPLEMENTATION

CLASS scooterbuilder DEFINITION INHERITING FROM vehiclebuilder.


PUBLIC SECTION.
METHODS:
buildframe REDEFINITION
,buildengine REDEFINITION
,buildwheels REDEFINITION
,builddoors REDEFINITION
.
ENDCLASS. "Scooterbuilder DEFINITION

CLASS scooterbuilder IMPLEMENTATION.


METHOD buildframe.
CREATE OBJECT vehicle EXPORTING vtype = 'Scooter'.
vehicle->add( EXPORTING key = 'frame'
part = 'Scooter Frame' ).
ENDMETHOD. "buildparta
METHOD buildengine.
vehicle->add( EXPORTING key = 'engine'
part = '50 cc' ).
ENDMETHOD. "buildpartb
METHOD buildwheels.
vehicle->add( EXPORTING key = 'wheels'
part = '2' ) .
ENDMETHOD. "buildwheels
METHOD builddoors.
vehicle->add( EXPORTING key = 'doors'
part = '0' ) .
ENDMETHOD. "builddoors

ENDCLASS. "Carbuilder IMPLEMENTATION

CLASS shop DEFINITION.


PUBLIC SECTION.
METHODS:
construct IMPORTING vehiclebuilder TYPE REF TO vehiclebuilder.
ENDCLASS. "shop DEFINITION

CLASS shop IMPLEMENTATION.


METHOD construct.
vehiclebuilder->buildframe( ).
vehiclebuilder->buildengine( ).

Version: 1.0
Side: 33
Project: Design Pattern

vehiclebuilder->buildwheels( ).
vehiclebuilder->builddoors( ).
ENDMETHOD. "construct
ENDCLASS. "shop IMPLEMENTATION

CLASS mainapp DEFINITION.


PUBLIC SECTION.
CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator.
CLASS-METHODS main.
ENDCLASS. "mainapp DEFINITION

CLASS mainapp IMPLEMENTATION.


METHOD main.
DATA: shop TYPE REF TO shop
,b1 TYPE REF TO scooterbuilder
,b2 TYPE REF TO carbuilder
,b3 TYPE REF TO motorcyclebuilder
.
* Create shop with vehiclle builders
CREATE OBJECT shop.
CREATE OBJECT b1 EXPORTING vtype = 'Scooter'.
CREATE OBJECT b2 EXPORTING vtype = 'Car'.
CREATE OBJECT b3 EXPORTING vtype = 'MotorCycle'.

* Construct and display vehicles


CALL METHOD shop->construct( b1 ).
b1->show( ).
CALL METHOD shop->construct( b2 ).
b2->show( ).
CALL METHOD shop->construct( b3 ).
b3->show( ).

ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).
Vehicle Type: Scooter
frame Scooter Frame
engine 50 cc
wheels 2
doors 0

Vehicle Type: Car


frame Car Frame
engine 2500 cc
wheels 4
doors 4

Vehicle Type: MotorCycle


frame Motorcycle Frame
engine 500 cc
wheels 2
doors 0

2.1.3 Factory Method


Creates an instance of several derived classes

2.1.3.1 Definition
Define an interface for creating an object, but let subclasses decide which class
to instantiate. Factory Method lets a class defer instantiation to subclasses.

Version: 1.0
Side: 34
Project: Design Pattern

2.1.3.2 UML class diagram

The product is a generelization of the concrete product, like the creator is a


generelization of the spacialized concretecreator. The ConcreteCreator have
dependency off Product Class

2.1.3.3 Participants
The classes and/or objects participating in this pattern are:
o Product (Page)
o defines the interface of objects the factory method creates
o ConcreteProduct (SkillsPage, EducationPage, ExperiencePage)
o implements the Product interface
o Creator (Document)
o declares the factory method, which returns an object of type
Product. Creator may also define a default implementation of the
factory method that returns a default ConcreteProduct object. may
call the factory method to create a Product object.
o ConcreteCreator (Report, Resume)
o overrides the factory method to return an instance of a
ConcreteProduct.

2.1.3.4 Sample code In C#


This structural code demonstrates the Factory method offering great flexibility
in creating different objects. The Abstract class may provide a default object,
but each subclass can instantiate an extended version of the object.

// Factory Method pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Factory.Structural
{

// MainApp test application

Version: 1.0
Side: 35
Project: Design Pattern

class MainApp
{
static void Main()
{
// An array of creators
Creator[] creators = new Creator[2];
creators[0] = new ConcreteCreatorA();
creators[1] = new ConcreteCreatorB();

// Iterate over creators and create products


foreach(Creator creator in creators)
{
Product product = creator.FactoryMethod();
Console.WriteLine("Created {0}",
product.GetType().Name);
}

// Wait for user


Console.Read();
}
}

// "Product"

abstract class Product


{
}

// "ConcreteProductA"

class ConcreteProductA : Product


{
}

// "ConcreteProductB"

class ConcreteProductB : Product


{
}

// "Creator"

abstract class Creator


{
public abstract Product FactoryMethod();
}

// "ConcreteCreator"

class ConcreteCreatorA : Creator


{
public override Product FactoryMethod()
{
return new ConcreteProductA();
}

Version: 1.0
Side: 36
Project: Design Pattern

// "ConcreteCreator"

class ConcreteCreatorB : Creator


{
public override Product FactoryMethod()
{
return new ConcreteProductB();
}
}
}

Output
Created ConcreteProductA
Created ConcreteProductB

This real-world code demonstrates the Factory method offering flexibility in


creating different documents. The derived Document classes Report and
Resume instantiate extended versions of the Document class. Here, the
Factory Method is called in the constructor of the Document base class.

// Factory Method pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Factory.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Note: constructors call Factory Method
Document[] documents = new Document[2];
documents[0] = new Resume();
documents[1] = new Report();

// Display document pages


foreach (Document document in documents)
{
Console.WriteLine("\n" + document.GetType().Name+ "--");
foreach (Page page in document.Pages)
{
Console.WriteLine(" " + page.GetType().Name);
}
}

// Wait for user


Console.Read();
}
}

Version: 1.0
Side: 37
Project: Design Pattern

// "Product"

abstract class Page


{
}

// "ConcreteProduct"

class SkillsPage : Page


{
}

// "ConcreteProduct"

class EducationPage : Page


{
}

// "ConcreteProduct"

class ExperiencePage : Page


{
}

// "ConcreteProduct"

class IntroductionPage : Page


{
}

// "ConcreteProduct"

class ResultsPage : Page


{
}

// "ConcreteProduct"

class ConclusionPage : Page


{
}

// "ConcreteProduct"

class SummaryPage : Page


{
}

// "ConcreteProduct"

class BibliographyPage : Page


{
}

// "Creator"

Version: 1.0
Side: 38
Project: Design Pattern

abstract class Document


{
private ArrayList pages = new ArrayList();

// Constructor calls abstract Factory method


public Document()
{
this.CreatePages();
}

public ArrayList Pages


{
get{ return pages; }
}

// Factory Method
public abstract void CreatePages();
}

// "ConcreteCreator"

class Resume : Document


{
// Factory Method implementation
public override void CreatePages()
{
Pages.Add(new SkillsPage());
Pages.Add(new EducationPage());
Pages.Add(new ExperiencePage());
}
}

// "ConcreteCreator"

class Report : Document


{
// Factory Method implementation
public override void CreatePages()
{
Pages.Add(new IntroductionPage());
Pages.Add(new ResultsPage());
Pages.Add(new ConclusionPage());
Pages.Add(new SummaryPage());
Pages.Add(new BibliographyPage());
}
}
}

Output
Resume -------
SkillsPage
EducationPage
ExperiencePage

Report -------
IntroductionPage

Version: 1.0
Side: 39
Project: Design Pattern

ResultsPage
ConclusionPage
SummaryPage
BibliographyPage

2.1.3.5 Sample code in ABAP


This structural code demonstrates the Factory method offering great flexibility
in creating different objects. The Abstract class may provide a default object,
but each subclass can instantiate an extended version of the object.

In ABAP Classes you can’t get the classname with build in functions.Often you
don’t need The classname, but sometimes when you process collection of
classes you need to do dependent class processes, and therefore you need to
know which class you are working with. Using a standard SAP class we are able
to get the class name. In the examples I have build this code into a macro for
easy use:

* Macro Definition
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.
* Call macro with parameter <instans object> <returning name>
?get_class_name product class_name.

REPORT zfactory_structural NO STANDARD PAGE HEADING LINE-SIZE 80.


CLASS product DEFINITION DEFERRED.
CLASS concreteproducta DEFINITION DEFERRED.
CLASS concreteproductb DEFINITION DEFERRED .

CLASS creator DEFINITION DEFERRED.


CLASS concretecreatora DEFINITION DEFERRED.
CLASS concretecreatorb DEFINITION DEFERRED.
CLASS cl_abap_typedescr DEFINITION LOAD.

data: moff type i


,slen type i
,mlen type i.

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 product DEFINITION ABSTRACT.


ENDCLASS. "product DEFINITION

CLASS concreteproducta DEFINITION INHERITING FROM product.


ENDCLASS. "concreteproducta DEFINITION

CLASS concreteproductb DEFINITION INHERITING FROM product.


ENDCLASS. "concreteproductB DEFINITION

Version: 1.0
Side: 40
Project: Design Pattern

CLASS creator DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
factorymethod ABSTRACT RETURNING value(product) TYPE REF TO product.
ENDCLASS. "product DEFINITION

CLASS concretecreatora DEFINITION INHERITING FROM creator.


PUBLIC SECTION.
METHODS:
factorymethod REDEFINITION.
ENDCLASS. "concretecreatora DEFINITION

CLASS concretecreatora IMPLEMENTATION.


METHOD factorymethod.
CREATE OBJECT product TYPE concreteproducta.
ENDMETHOD. "factoryproduct
ENDCLASS. "concretecreatora IMPLEMENTATION

CLASS concretecreatorb DEFINITION INHERITING FROM creator.


PUBLIC SECTION.
METHODS:
factorymethod REDEFINITION.
ENDCLASS. "concretecreatorb DEFINITION

CLASS concretecreatorb IMPLEMENTATION.


METHOD factorymethod.
CREATE OBJECT product TYPE concreteproductb.
ENDMETHOD. "factoryproduct
ENDCLASS. "concretecreatorb IMPLEMENTATION

CLASS mainapp DEFINITION.


PUBLIC SECTION.
CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator.
CLASS-METHODS main.
ENDCLASS. "mainapp DEFINITION

CLASS mainapp IMPLEMENTATION.


METHOD main.
DATA: creator TYPE REF TO creator
,concretecreatora TYPE REF TO concretecreatora
,concretecreatorb TYPE REF TO concretecreatorb
,product TYPE REF TO product
,class_name TYPE abap_abstypename
.
FIELD-SYMBOLS <fs> TYPE ANY.

CREATE OBJECT concretecreatora.


APPEND concretecreatora TO oa_creator_coll.

CREATE OBJECT concretecreatorb.


APPEND concretecreatorb TO oa_creator_coll.

LOOP AT oa_creator_coll ASSIGNING <fs>.


?get_class_name <fs> class_name.
CASE class_name.
WHEN 'CONCRETECREATORA'.
WRITE: / 'ConcreteCreatorA Creates Product A'.
WHEN 'CONCRETECREATORB'.
WRITE: / 'ConcreteCreatorB Creates Product B'.
ENDCASE.
creator = <fs>.
product = creator->factorymethod( ).
?get_class_name product class_name.
WRITE: / 'Product =',class_name.
ENDLOOP.

Version: 1.0
Side: 41
Project: Design Pattern

ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Output
ConcreteCreatorA Creates ProductA
Product =
CONCRETEPRODUCTA
ConcreteCreatorB Creates ProductB
Product =
CONCRETEPRODUCTB

2.1.3.6 Sample code in ABAP


This structural code demonstrates the Factory method offering great flexibility
in creating different objects.

In this example the Abstract class have been replaced by using interfaces.
Each subclass must implement the interface and each subclass can instantiate
their own class versiob decoupled from a common parent class as long it
implement the same interface.

REPORT zfactory_structural NO STANDARD PAGE HEADING LINE-SIZE 80.


CLASS cl_abap_typedescr DEFINITION LOAD.

DATA: moff TYPE i


,slen TYPE i
,mlen TYPE i.

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.

INTERFACE product.
TYPES ty_productname(30) TYPE c.
DATA: name TYPE ty_productname.
METHODS:
get_name RETURNING value(name) TYPE ty_productname.
ENDINTERFACE.

CLASS concreteproducta DEFINITION.


PUBLIC SECTION.
INTERFACES:
product.
ENDCLASS. "concreteproducta DEFINITION

CLASS concreteproducta IMPLEMENTATION.


METHOD product~get_name.
name = 'ConcreteProductA'.
ENDMETHOD. "product~getname
ENDCLASS. "concreteproducta IMPLEMENTATION

CLASS concreteproductb DEFINITION.

Version: 1.0
Side: 42
Project: Design Pattern

PUBLIC SECTION.
INTERFACES:
product.
ENDCLASS. "concreteproductB DEFINITION

CLASS concreteproductb IMPLEMENTATION.


METHOD product~get_name.
name = 'ConCreteProductB'.
ENDMETHOD. "product~getname
ENDCLASS. "concreteproductB IMPLEMENTATION

INTERFACE creator.
METHODS:
factorymethod RETURNING value(product) TYPE REF TO product.
ENDINTERFACE.

CLASS concretecreatora DEFINITION.


PUBLIC SECTION.
INTERFACES:
creator.
ENDCLASS. "concretecreatora DEFINITION

CLASS concretecreatora IMPLEMENTATION.


METHOD creator~factorymethod.
CREATE OBJECT product TYPE concreteproducta.
ENDMETHOD. "factoryproduct
ENDCLASS. "concretecreatora IMPLEMENTATION

CLASS concretecreatorb DEFINITION.


PUBLIC SECTION.
INTERFACES:
creator.
ENDCLASS. "concretecreatorb DEFINITION

CLASS concretecreatorb IMPLEMENTATION.


METHOD creator~factorymethod.
CREATE OBJECT product TYPE concreteproductb.
ENDMETHOD. "factoryproduct
ENDCLASS. "concretecreatorb IMPLEMENTATION

CLASS mainapp DEFINITION.


PUBLIC SECTION.
CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator.
CLASS-METHODS main.
ENDCLASS. "mainapp DEFINITION

CLASS mainapp IMPLEMENTATION.


METHOD main.
data: concretecreatora TYPE REF TO concretecreatora
,concretecreatorb TYPE REF TO concretecreatorb
,product TYPE REF TO product
,product_name(30) type c
,class_name TYPE abap_abstypename
.
FIELD-SYMBOLS <fs> TYPE REF TO creator.

CREATE OBJECT concretecreatora.


APPEND concretecreatora TO oa_creator_coll.

CREATE OBJECT concretecreatorb.


APPEND concretecreatorb TO oa_creator_coll.

LOOP AT oa_creator_coll ASSIGNING <fs>.

* Call macro to find out which Creator and Product are active
?get_class_name <fs> class_name.

Version: 1.0
Side: 43
Project: Design Pattern

CASE class_name.
WHEN 'CONCRETECREATORA'.
WRITE: / 'ConcreteCreatorA Creates Product A'.
WHEN 'CONCRETECREATORB'.
WRITE: / 'ConcreteCreatorB Creates Product B'.
ENDCASE.

product = <fs>->factorymethod( ) .
?get_class_name product class_name.
product_name = product->get_name( ).
WRITE: / 'Class= ', class_name,'Product =',product_name.
ENDLOOP.

ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Output
ConcreteCreatorA Creates ProductA
Class =
CONCRETEPRODUCTA
Product = ConcreteProductA
ConcreteCreatorB Creates ProductB
Class =
CONCRETEPRODUCTB
Product = ConcreteProductB

2.1.3.7 Sample code in ABAP

This real-world code demonstrates the Factory method offering flexibility in


creating different documents. The derived Document classes Report and
Resume instantiate extended versions of the Document class. Here, the
Factory Method is called in the constructor of the Document derived class, in
ABAP you cannot call an abstract method from the abstract base class
constructor.

REPORT zfactory_structural NO STANDARD PAGE HEADING LINE-SIZE 80.


CLASS cl_abap_typedescr DEFINITION LOAD.

DATA: moff TYPE i


,slen TYPE i
,mlen TYPE i.

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 page DEFINITION ABSTRACT.


ENDCLASS. "page DEFINITION

CLASS skillspage DEFINITION INHERITING FROM page.


ENDCLASS. "skillspage DEFINITION

CLASS educationpage DEFINITION INHERITING FROM page.

Version: 1.0
Side: 44
Project: Design Pattern

ENDCLASS. "educationpage DEFINITION

CLASS experiencepage DEFINITION INHERITING FROM page.


ENDCLASS. "experiencepage DEFINITION

CLASS introductionpage DEFINITION INHERITING FROM page.


ENDCLASS. "introductionpage DEFINITION

CLASS resultspage DEFINITION INHERITING FROM page.


ENDCLASS. "resultspage DEFINITION

CLASS conclusionpage DEFINITION INHERITING FROM page.


ENDCLASS. "conclusionpage DEFINITION

CLASS summarypage DEFINITION INHERITING FROM page.


ENDCLASS. "summarypage DEFINITION

CLASS bibliographypage DEFINITION INHERITING FROM page.


ENDCLASS. "bibliographypage DEFINITION

CLASS document DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS:
createpages ABSTRACT
,pages EXPORTING pages TYPE ANY TABLE
.
PROTECTED SECTION.
DATA:
oa_pages_coll TYPE TABLE OF REF TO page.
ENDCLASS. "document DEFINITION

CLASS document IMPLEMENTATION.

METHOD pages.
pages[] = oa_pages_coll[].
ENDMETHOD. "pages

ENDCLASS. "document IMPLEMENTATION

CLASS resume DEFINITION INHERITING FROM document.


PUBLIC SECTION.
METHODS:
constructor
,createpages REDEFINITION.
ENDCLASS. "resume DEFINITION

CLASS resume IMPLEMENTATION.


METHOD constructor.
super->constructor( ).
CALL METHOD me->createpages.
ENDMETHOD. "constructor

METHOD createpages.
DATA: page TYPE REF TO page.
CREATE OBJECT page TYPE skillspage.
APPEND page TO oa_pages_coll.

CREATE OBJECT page TYPE educationpage.


APPEND page TO oa_pages_coll.

CREATE OBJECT page TYPE experiencepage.


APPEND page TO oa_pages_coll.

ENDMETHOD. "createpages
ENDCLASS. "resume IMPLEMENTATION

Version: 1.0
Side: 45
Project: Design Pattern

CLASS report DEFINITION INHERITING FROM document.


PUBLIC SECTION.
METHODS:
constructor
,createpages REDEFINITION.
ENDCLASS. "report DEFINITION

CLASS report IMPLEMENTATION.


METHOD constructor.
super->constructor( ).
CALL METHOD me->createpages.
ENDMETHOD. "constructor

METHOD createpages.
DATA: page TYPE REF TO page.
CREATE OBJECT page TYPE introductionpage.
APPEND page TO oa_pages_coll.

CREATE OBJECT page TYPE resultspage.


APPEND page TO oa_pages_coll.

CREATE OBJECT page TYPE conclusionpage.


APPEND page TO oa_pages_coll.

CREATE OBJECT page TYPE summarypage.


APPEND page TO oa_pages_coll.

CREATE OBJECT page TYPE bibliographypage.


APPEND page TO oa_pages_coll.

ENDMETHOD. "createpages
ENDCLASS. "report IMPLEMENTATION

CLASS mainapp DEFINITION.


PUBLIC SECTION.
CLASS-DATA: oa_document_coll TYPE TABLE OF REF TO document.
CLASS-METHODS main.
ENDCLASS. "mainapp DEFINITION

CLASS mainapp IMPLEMENTATION.


METHOD main.
DATA: document TYPE REF TO document
,resume TYPE REF TO resume
,report TYPE REF TO report
,page TYPE REF TO page
,class_name TYPE abap_abstypename
,pages_coll TYPE TABLE OF REF TO page.
.
FIELD-SYMBOLS: <fs_document> TYPE REF TO document
,<fs_page> TYPE REF TO page.

CREATE OBJECT resume.


APPEND resume TO oa_document_coll.

CREATE OBJECT report.


APPEND report TO oa_document_coll.

* Loop at all documents


LOOP AT oa_document_coll ASSIGNING <fs_document>.
* Call macro to find out which Creator and Product are active
?get_class_name <fs_document> class_name.
CASE class_name.
WHEN 'RESUME'.
WRITE: / 'Resume contains following pages:', / sy-uline.
CALL METHOD <fs_document>->pages( IMPORTING pages = pages_coll ).
* Loop at all pages in document Resume

Version: 1.0
Side: 46
Project: Design Pattern

LOOP AT pages_coll ASSIGNING <fs_page>.


?get_class_name <fs_page> class_name.
WRITE: / class_name.
ENDLOOP.
WHEN 'REPORT'.
WRITE: / 'Report contains following pages:', / sy-uline.
CALL METHOD <fs_document>->pages( IMPORTING pages = pages_coll ).
* Loop at all pages in document Resume
LOOP AT pages_coll ASSIGNING <fs_page>.
?get_class_name <fs_page> class_name.
WRITE: / class_name.
ENDLOOP.
ENDCASE.
ENDLOOP.

ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).
Output:

Resume contains following pages:

SKILLSPAGE
EDUCATIONPAGE
EXPERIENCEPAGE
Report contains following pages:

INTRODUCTIONPAGE
RESULTSPAGE
CONCLUSIONPAGE
SUMMARYPAGE
BIBLIOGRAPHYPAGE

2.1.4 Prototype
A fully initialized instance to be copied or cloned

2.1.4.1 Definition
Specify the kind of objects to create using a prototypical instance, and create
new objects by copying this prototype.

2.1.4.2 Used for


Prototype pattern is usally used to create objects when the process of object
creation is time consuming when done from scratch. In this case an existing
object is used as an prototype and similar objects are constructed using this
prototype (without using constructor)

Version: 1.0
Side: 47
Project: Design Pattern

2.1.4.3 UML class diagram

2.1.4.4 Participants
The classes and/or objects participating in this pattern are:
o Prototype (ColorPrototype)
o declares an interface for cloning itself
o ConcretePrototype (Color)
o implements an operation for cloning itself
o Client (ColorManager)
o creates a new object by asking a prototype to clone itself

2.1.4.5 Sample code In C#


This structural code demonstrates the Prototype pattern in which new objects
are created by copying pre-existing objects (prototypes) of the same class.

// Prototype pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Prototype.Structural
{

// MainApp test application

class MainApp
{

static void Main()


{
// Create two instances and clone each

ConcretePrototype1 p1 = new ConcretePrototype1("I");


ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
Console.WriteLine ("Cloned: {0}", c1.Id);

Version: 1.0
Side: 48
Project: Design Pattern

ConcretePrototype2 p2 = new ConcretePrototype2("II");


ConcretePrototype2 c2 = (ConcretePrototype2)p2.Clone();
Console.WriteLine ("Cloned: {0}", c2.Id);

// Wait for user


Console.Read();
}
}

// "Prototype"

abstract class Prototype


{
private string id;

// Constructor
public Prototype(string id)
{
this.id = id;
}

// Property
public string Id
{
get{ return id; }
}

public abstract Prototype Clone();


}

// "ConcretePrototype1"

class ConcretePrototype1 : Prototype


{
// Constructor
public ConcretePrototype1(string id) : base(id)
{
}

public override Prototype Clone()


{
// Shallow copy
return (Prototype)this.MemberwiseClone();
}
}

// "ConcretePrototype2"

class ConcretePrototype2 : Prototype


{
// Constructor
public ConcretePrototype2(string id) : base(id)
{
}

Version: 1.0
Side: 49
Project: Design Pattern

public override Prototype Clone()


{
// Shallow copy
return (Prototype)this.MemberwiseClone();
}
}
}

Output
Cloned: I
Cloned: II

2.1.4.6 Sample code In ABAP


This structural code demonstrates the Prototype pattern in which new objects
are created by copying pre-existing objects (prototypes) of the same class.
We uses UP CASTING where the code can’t be checked before runtime.

*&---------------------------------------------------------------------*
*& Report ZPROTOTYPE_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zprototype_structural.

*----------------------------------------------------------------------*
* CLASS prototype DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS prototype DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING id TYPE string
,get_id RETURNING value(id) TYPE string
,clone ABSTRACT RETURNING value(prototype) TYPE REF TO prototype
.
PRIVATE SECTION.
DATA: id TYPE string.
ENDCLASS. "prototype DEFINITION

*----------------------------------------------------------------------*
* CLASS prototype IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS prototype IMPLEMENTATION.
METHOD constructor.
me->id = id.
ENDMETHOD. "constructor
METHOD get_id.
id = me->id.

Version: 1.0
Side: 50
Project: Design Pattern

ENDMETHOD. "get_id
ENDCLASS. "prototype IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS concreteprototype1 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype1 DEFINITION INHERITING FROM prototype.
PUBLIC SECTION.
METHODS:
clone REDEFINITION.
ENDCLASS. "concreteprototype1 DEFINITION
*----------------------------------------------------------------------*
* CLASS concreteprototype1 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype1 IMPLEMENTATION.
METHOD clone.
prototype = me.
ENDMETHOD. "clone
ENDCLASS. "concreteprototype1 IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS concreteprototype2 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype2 DEFINITION INHERITING FROM prototype.
PUBLIC SECTION.
METHODS:
clone REDEFINITION.
ENDCLASS. "concreteprototype2 DEFINITION
*----------------------------------------------------------------------*
* CLASS concreteprototype2 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype2 IMPLEMENTATION.
METHOD clone.
prototype = me.
ENDMETHOD. "clone
ENDCLASS. "concreteprototype2 IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*

Version: 1.0
Side: 51
Project: Design Pattern

*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
data: p1 type REF TO concreteprototype1
,c1 type REF TO concreteprototype1
,p2 TYPe REF TO concreteprototype2
,c2 type REF TO concreteprototype2
,id type string
.

field-SYMBOLS <fs> type REF TO prototype.

* Create two instances and clone each


create object p1 exporting id = 'I'.
c1 ?= p1->clone( ).
id = c1->get_id( ).
write: / 'Cloned: {0}', id.

* Down Casting uses assign operator ?= as it can not be checked


* before runtine
create object p2 exporting id = 'II'.
c2 ?= p2->clone( ).
id = c2->get_id( ).
write: / 'Cloned: {0}', id.

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).
Output
Program ZPROTOTYPE_STRUCTURAL

Cloned: {0} I
Cloned: {0} II

2.1.4.7 Sample code In C#


This real-world code demonstrates the Prototype pattern in which new Color
objects are created by copying pre-existing, user-defined Colors of the same
type.

// Prototype pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Prototype.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()

Version: 1.0
Side: 52
Project: Design Pattern

{
ColorManager colormanager = new ColorManager();

// Initialize with standard colors


colormanager["red" ] = new Color(255, 0, 0);
colormanager["green"] = new Color( 0, 255, 0);
colormanager["blue" ] = new Color( 0, 0, 255);

// User adds personalized colors


colormanager["angry"] = new Color(255, 54, 0);
colormanager["peace"] = new Color(128, 211, 128);
colormanager["flame"] = new Color(211, 34, 20);

Color color;

// User uses selected colors


string name = "red";
color = colormanager[name].Clone() as Color;

name = "peace";
color = colormanager[name].Clone() as Color;

name = "flame";
color = colormanager[name].Clone() as Color;

// Wait for user


Console.Read();
}
}

// "Prototype"

abstract class ColorPrototype


{
public abstract ColorPrototype Clone();
}

// "ConcretePrototype"

class Color : ColorPrototype


{
private int red;
private int green;
private int blue;

// Constructor
public Color(int red, int green, int blue)
{
this.red = red;
this.green = green;
this.blue = blue;
}

// Create a shallow copy


public override ColorPrototype Clone()
{

Version: 1.0
Side: 53
Project: Design Pattern

Console.WriteLine(
"Cloning color RGB: {0,3},{1,3},{2,3}",
red, green, blue);

return this.MemberwiseClone() as ColorPrototype;


}
}

// Prototype manager

class ColorManager
{
Hashtable colors = new Hashtable();

// Indexer
public ColorPrototype this[string name]
{
get
{
return colors[name] as ColorPrototype;
}
set
{
colors.Add(name, value);
}
}
}
}

Output
Cloning color RGB: 255, 0, 0
Cloning color RGB: 128,211,128
Cloning color RGB: 211, 34, 20

2.1.4.8 Sample code In ABAP


This real-world code demonstrates the Prototype pattern in which new Color
objects are created by copying pre-existing, user-defined Colors of the same
type.

In the clone method this example does not create a new instance, but merely
returns actual instans and thereby you have two variables pointing to the same
instance. A true clone would create a new instance copy all the instance
attributes from actual instanceto the new clone and thereby you would have a
real clone that can live it’s own life.

*&---------------------------------------------------------------------*
*& Report ZPROTOTYPE_REALWORLD
*&
*&---------------------------------------------------------------------*
*&

Version: 1.0
Side: 54
Project: Design Pattern

*&
*&---------------------------------------------------------------------*

REPORT zprototype_realworld.

*----------------------------------------------------------------------*
* CLASS colorprototype DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS colorprototype DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
clone ABSTRACT RETURNING value(colorprototype) TYPE REF TO colorprototype.
ENDCLASS. "prototype DEFINITION

*----------------------------------------------------------------------*
* CLASS color DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS color DEFINITION INHERITING FROM colorprototype.
PUBLIC SECTION.
METHODS:
constructor IMPORTING red TYPE i
green TYPE i
blue TYPE i
,clone REDEFINITION.
PROTECTED SECTION.
DATA: xred TYPE i
,xgreen TYPE i
,xblue TYPE i.
ENDCLASS. "concreteprototype1 DEFINITION
*----------------------------------------------------------------------*
* CLASS color IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS color IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
xred = red.
xgreen = green.
xblue = blue.
ENDMETHOD. "constructor

METHOD clone.
WRITE: / 'Cloning color RGB: {0,3},{1,3},{2,3}',
me->xred, me->xgreen, me->xblue.
colorprototype = me.
ENDMETHOD. "clone
ENDCLASS. "concreteprototype1 IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS colormanager DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS colormanager DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF ty_colors
,name TYPE string
,color TYPE REF TO colorprototype
,END OF ty_colors.

Version: 1.0
Side: 55
Project: Design Pattern

DATA: colors TYPE HASHED TABLE OF ty_colors


WITH UNIQUE KEY name.

METHODS:
get IMPORTING name TYPE string RETURNING value(Pcolors) TYPE REF TO colorprototype
,set IMPORTING name TYPE string pcolor TYPE REF TO colorprototype.
.
ENDCLASS. "colormanager DEFINITION

*----------------------------------------------------------------------*
* CLASS colormanager IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS colormanager IMPLEMENTATION.
METHOD get.
DATA buffer TYPE ty_colors.
FIELD-SYMBOLS <fs> TYPE ty_colors.
READ TABLE me->colors WITH TABLE KEY name = name INTO buffer.
Pcolors = buffer-color.
ENDMETHOD. "get

method set.
DATA buffer TYPE ty_colors.
buffer-name = name.
buffer-color = pcolor.
INSERT buffer INTO TABLE colors.
endmethod.

ENDCLASS. "colormanager IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
data: colormanager type REF TO colormanager
,!color type REF TO color
,name type string
.

* Create the color manager


create OBJECT colormanager.
create OBJECT !color EXPORTING red = 255 green = 0 blue = 0 .
colormanager->set( EXPORTING name = 'red' pcolor = !color ).

create OBJECT !color EXPORTING red = 0 green = 255 blue = 0 .


colormanager->set( EXPORTING name = 'green' pcolor = !color ).

create OBJECT !color EXPORTING red = 0 green = 0 blue = 255 .


colormanager->set( EXPORTING name = 'blue' pcolor = !color ).

Version: 1.0
Side: 56
Project: Design Pattern

create OBJECT !color EXPORTING red = 255 green = 54 blue = 0 .


colormanager->set( EXPORTING name = 'angry' pcolor = !color ).

create OBJECT !color EXPORTING red = 128 green = 211 blue = 128 .
colormanager->set( EXPORTING name = 'peace' pcolor = !color ).

create OBJECT !color EXPORTING red = 211 green = 34 blue = 20 .


colormanager->set( EXPORTING name = 'flame' pcolor = !color ).

name = 'red'.
!color ?= colormanager->get( name ). "!color is a colorprototype
!color ?= !color->clone( ). "!color is a color

name = 'peace'.
!color ?= colormanager->get( name ). "!color is a colorprototype
!color ?= !color->clone( ). "!color is a color

name = 'flame'.
!color ?= colormanager->get( name ). "!color is a colorprototype
!color ?= !color->clone( ). "!color is a color

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Output:
Program ZPROTOTYPE_STRUCTURAL

Cloning color RGB: {0,3},{1,3},{2,3} 255 0 0


Cloning color RGB: {0,3},{1,3},{2,3} 128 211 128
Cloning color RGB: {0,3},{1,3},{2,3} 211 34 20

2.1.5 Singleton
A class of which only a single instance can exist

2.1.5.1 Definition
Ensure a class has only one instance and provide a global point of access to it.

In software engineering, the singleton pattern is a design pattern that is


used to restrict instantiation of a class to one object. This is useful when
exactly one object is needed to coordinate actions across the system.
Sometimes it is generalized to systems that operate more efficiently when only
one or a few objects exist. It is also considered an anti-pattern since it is often
used as a euphemism for global variable.

2.1.5.2 Common Use

• Abstract Factory, Builder, and Prototype patterns can use Singletons in


their implementation.

Version: 1.0
Side: 57
Project: Design Pattern

• Facade objects are often Singletons because only one Facade object is
required.
• State objects are often Singletons.
• Singletons are often preferred to global variables because:
o They don't pollute the global namespace (or, in languages with
namespaces, their containing namespace) with unnecessary
variables.
o They permit lazy allocation and initialization, where global variables
in many languages will always consume resources.
• Singletons behave differently depending on the lifetime of the virtual
machine. While a software development kit may start a new virtual
machine for every run which results in a new instance of the singleton
being created, calls to a singleton e.g. within the virtual machine of an
application server behave differently. There the virtual machine remains
alive, therefore the instance of the singleton remains as well. Running
the code again therefore can retrieve the "old" instance of the singleton
which then may be contaminated with values in local fields which are the
result of the first run.
• Main application in abap, if implemented as OOP style the
mainapplication class uses local singleton to assure that the program is
not run several times.

2.1.5.3 Implementation
The singleton pattern is implemented by creating a class with a method that
creates a new instance of the class if one does not exist.

If an instance already exists, it simply returns a reference to that object. To


make sure that the object cannot be instantiated any other way, the
constructor is made either private or protected.

Note the distinction between a simple static instance of a class and a


singleton: although a singleton can be implemented as a static instance, it can
also be lazily constructed, requiring no memory or resources until needed.
Another notable difference is that static member classes cannot implement an
interface, unless that interface is simply a marker. So if the class has to realize
a contract expressed by an interface, you really have to make it a singleton.

The singleton pattern must be carefully constructed in multi-threaded


applications. If two threads are to execute the creation method at the same
time when a singleton does not yet exist, they both must check for an instance
of the singleton and then only one should create the new one. If the
programming language has concurrent processing capabilities the method
should be constructed to execute as a mutually exclusive operation.
The classic solution to this problem is to use mutual exclusion on the class that
indicates that the object is being instantiated.

Version: 1.0
Side: 58
Project: Design Pattern

The singleton are not useful for inheritage, as all inheritated classes only have
one common instance and because the superclass only have one attribute with
the created instance. Singleton classes should therefore be marked as FINAL.
Another reason for bad inheritance, is if the singleton superclass tries to create
instances, as the superclass does not know the local class, therefore we are
getting type casting problems. You can however use singleton in inheritage if
your own class has been registered in the dictionary {SE24} and if your class
has been registered as a friend to the singleton superclass. Your singleton
should then have an collection af classes of which only one instance per class
are allowed. But then you must use dynamic creation and thereby you need to
export the classname as a parameter to get_instance.

2.1.5.4 UML class diagram

2.1.5.5 Participants
The classes and/or objects participating in this pattern are:

o Singleton (LoadBalancer)
o defines an Instance operation that lets clients access its unique
instance.

Instance is a class operation responsible for creating and maintaining its own
unique instance.

2.1.5.6 Sample code In C#


This structural code demonstrates the Singleton pattern which assures only a
single instance (the singleton) of the class can be created.

// Singleton pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Singleton.Structural
{

// MainApp test application

class MainApp
{

static void Main()

Version: 1.0
Side: 59
Project: Design Pattern

{
// Constructor is protected -- cannot use new
Singleton s1 = Singleton.Instance();
Singleton s2 = Singleton.Instance();

if (s1 == s2)
{
Console.WriteLine("Objects are the same instance");
}

// Wait for user


Console.Read();
}
}

// "Singleton"

class Singleton
{
private static Singleton instance;

// Note: Constructor is 'protected'


protected Singleton()
{
}

public static Singleton Instance()


{
// Use 'Lazy initialization'
if (instance == null)
{
instance = new Singleton();
}

return instance;
}
}
}

Output
ÎObjects are the same instance

2.1.5.7 Sample code In ABAP


This structural code demonstrates the Singleton pattern which assures only a
single instance (the singleton) of the class can be created.

*&---------------------------------------------------------------------*
*& Report ZSINGLETON_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&

Version: 1.0
Side: 60
Project: Design Pattern

*&---------------------------------------------------------------------*

REPORT zsingleton_structural.

*----------------------------------------------------------------------*
* CLASS singleton DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS singleton DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
METHODS:
constructor.
CLASS-METHODS:
instance RETURNING value(instance) TYPE REF TO singleton.
PRIVATE SECTION.
CLASS-DATA x_instance TYPE REF TO singleton.
ENDCLASS. "singleton DEFINITION

*----------------------------------------------------------------------*
* CLASS singleton IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS singleton IMPLEMENTATION.
METHOD constructor.
ENDMETHOD. "constructor

METHOD instance.
IF x_instance IS INITIAL.
CREATE OBJECT x_instance.
ENDIF.
instance = x_instance.
ENDMETHOD. "instance

ENDCLASS. "singleton IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: s1 TYPE REF TO singleton
,s2 TYPE REF TO singleton
.

* Constructor is protected --- cannot use create object


s1 = singleton=>instance( ).
s2 = singleton=>instance( ).

IF s1 = s2.
WRITE: / 'Objects are the same instance'.
ENDIF.

Version: 1.0
Side: 61
Project: Design Pattern

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).
------------------------------------
Objects are the same instance

2.1.5.8 Sample code In C#


This real-world code demonstrates the Singleton pattern as a LoadBalancing
object. Only a single instance (the singleton) of the class can be created
because servers may dynamically come on- or off-line and every request must
go throught the one object that has knowledge about the state of the (web)
farm.

// Singleton pattern -- Real World example

using System;
using System.Collections;
using System.Threading;

namespace DoFactory.GangOfFour.Singleton.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

// Same instance?
if (b1 == b2 && b2 == b3 && b3 == b4)
{
Console.WriteLine("Same instance\n");
}

// All are the same instance -- use b1 arbitrarily


// Load balance 15 server requests
for (int i = 0; i < 15; i++)
{
Console.WriteLine(b1.Server);
}

// Wait for user


Console.Read();
}
}

Version: 1.0
Side: 62
Project: Design Pattern

// "Singleton"

class LoadBalancer
{
private static LoadBalancer instance;
private ArrayList servers = new ArrayList();

private Random random = new Random();

// Lock synchronization object


private static object syncLock = new object();

// Constructor (protected)
protected LoadBalancer()
{
// List of available servers
servers.Add("ServerI");
servers.Add("ServerII");
servers.Add("ServerIII");
servers.Add("ServerIV");
servers.Add("ServerV");
}

public static LoadBalancer GetLoadBalancer()


{
// Support multithreaded applications through
// 'Double checked locking' pattern which (once
// the instance exists) avoids locking each
// time the method is invoked
if (instance == null)
{
lock (syncLock)
{
if (instance == null)
{
instance = new LoadBalancer();
}
}
}

return instance;
}

// Simple, but effective random load balancer

public string Server


{
get
{
int r = random.Next(servers.Count);
return servers[r].ToString();
}
}
}
}

Version: 1.0
Side: 63
Project: Design Pattern

Output
Same instance

ServerIII
ServerII
ServerI
ServerII
ServerI
ServerIII
ServerI
ServerIII
ServerIV
ServerII
ServerII
ServerIII
ServerIV
ServerII
ServerIV

2.1.5.9 Sample code In ABAP


This real-world code demonstrates the Singleton pattern as a LoadBalancing
object. Only a single instance (the singleton) of the class can be created
because servers may dynamically come on- or off-line and every request must
go throught the one object that has knowledge about the state of the (web)
farm.
*&---------------------------------------------------------------------*
*& Report ZSINGLETON_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zsingleton_structural.

*----------------------------------------------------------------------*
* CLASS loadbalancer DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS loadbalancer DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
METHODS:
constructor
,server RETURNING value(pserver) TYPE string
.
CLASS-METHODS:
getloadbalancer RETURNING value(instance) TYPE REF TO loadbalancer.
PRIVATE SECTION.
CLASS-DATA x_instance TYPE REF TO loadbalancer.
DATA: servers TYPE TABLE OF string
.
METHODS:
add IMPORTING servername TYPE string
,get RETURNING value(servername) TYPE string
.
ENDCLASS. "singleton DEFINITION

*----------------------------------------------------------------------*

Version: 1.0
Side: 64
Project: Design Pattern

* CLASS loadbalancer IMPLEMENTATION


*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS loadbalancer IMPLEMENTATION.
METHOD constructor.
* Create 5 servers
add( EXPORTING servername = 'Server I' ).
add( EXPORTING servername = 'Server II' ).
add( EXPORTING servername = 'Server III' ).
add( EXPORTING servername = 'Server IV' ).
add( EXPORTING servername = 'Server V' ).

ENDMETHOD. "constructor

METHOD getloadbalancer.
IF x_instance IS INITIAL.
CREATE OBJECT x_instance.
ENDIF.
instance = x_instance.
ENDMETHOD. "instance

METHOD add.
INSERT servername INTO TABLE servers.
ENDMETHOD. "add

METHOD get.
DATA: numofservers TYPE i
,serverindex TYPE i
,random TYPE REF TO cl_abap_random
,seed TYPE i .

seed = cl_abap_random=>seed( ).
random = cl_abap_random=>create( seed ).

DESCRIBE TABLE servers LINES numofservers.


TRY.
serverindex = random->intinrange( low = 1 high = numofservers ).
CATCH cx_abap_random .
ENDTRY.

READ TABLE servers INDEX serverindex INTO servername.


ENDMETHOD. "get

METHOD server.
pserver = me->get( ).
ENDMETHOD. "server

ENDCLASS. "singleton IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*

Version: 1.0
Side: 65
Project: Design Pattern

CLASS mainapp IMPLEMENTATION.


METHOD main.
DATA: b1 TYPE REF TO loadbalancer
,b2 TYPE REF TO loadbalancer
,b3 TYPE REF TO loadbalancer
,b4 TYPE REF TO loadbalancer
,i TYPE i
,s TYPE string
.

* Constructor is protected --- cannot use create object


b1 = loadbalancer=>getloadbalancer( ).
b2 = loadbalancer=>getloadbalancer( ).
b3 = loadbalancer=>getloadbalancer( ).
b4 = loadbalancer=>getloadbalancer( ).

IF b1 = b2 AND b2 = b3 AND b3 = b4 .
WRITE: / 'Objects are the same instance'.
ENDIF.

* All are the same server, use b1 arbitraily


DO 15 TIMES.
s = b1->server( ).
WRITE: / s.
ENDDO.

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Objects are the same instance


Server IV
Server V
Server III
Server III
Server I
Server V
Server I
Server IV
Server III
Server II
Server II
Server IV
Server I
Server II
Server V

2.1.5.10 Sample code In ABAP for Application


If you wish your program uses the object oriented paragime fully, you should
probaly use a main application class. This class should follow the singleton
pattern, as you probaly does not whish your program are able to start severel
application sessions.

I suggest you allways use local application class, since the singleton have
severe problems with inheritage. Give your application class the name
lcl_application. As singleton pattern describe, your class should be registered

Version: 1.0
Side: 66
Project: Design Pattern

as CREATE PRIVATE. The default static method should be name RUN() without
parameters.

CLASS lcl_application DEFINITION CREATE PRIVATE.


ENDCLASS.

2.2 Structural Patterns


2.2.1 Adapter
Match interfaces of different classes

2.2.1.1 Definition
Convert the interface of a class into another interface clients expect. Adapter
lets classes work together that couldn't otherwise because of incompatible
interfaces.

In computer programming, the adapter design pattern (often referred to as


the wrapper pattern or simply a wrapper) 'adapts' one interface for a class into
one that a client expects.

An adapter allows classes to work together that normally could not because of
incompatible interfaces by wrapping its own interface around that of an already
existing class.

The adapter is also responsible for handling any logic necessary to transform
data into a form that is useful for the consumer. For instance, if multiple
boolean values are stored as a single integer but your consumer requires a
'true'/'false', the adapter would be responsible for extracting the appropriate
values from the integer value.

There are two types of adapter patterns:

• The Object Adapter pattern - In this type of adapter pattern, the adapter
contains an instance of the class it wraps. In this situation, the adapter
makes calls to the instance of the wrapped object.

• The Class Adapter pattern - This type of adapter uses multiple


inheritance to achieve its goal. The adapter is created inheriting
interfaces from both the interface that is expected and the interface that
is pre-existing. Note that when the adapter must adapt multiple
adaptees, the Class Adapter pattern cannot be used in languages such as
Java that do not support multiple inheritance.

Version: 1.0
Side: 67
Project: Design Pattern

ObjectAdapter ClassAdapter

The object adapter pattern expressed The class adapter pattern expressed in
in UML. The adapter hides the UML.
adaptee's interface from the client.

The adapter pattern is useful in situations where an already existing class


provides some or all of the services you need but does not use the interface
you need. A good real life example is an adapter that converts the interface of
a Document Object Model of an XML document into a tree structure that can
be displayed.

2.2.1.2 Common Use

The ABAP language does not support multiple inheritage, but support
interfaces. With interfaces you are able to use the same interface in different
classes. You are also able to let one class use different and several interfaces
and thereby accomplish the same effect as in multiple inheritage.

A typical solution in SAP where you want to use adapters are when you in a
dialog application want to have an object tree shown in the left control. This
tree might have different objects to show. Therefore you create a number of
interfaces that all the objects involved should be able to respond to e.g. open
or show yourself. Every objects that can be part of the tree implement the
interface.

Version: 1.0
Side: 68
Project: Design Pattern

2.2.1.3 UML class diagram

2.2.1.4 Participants
The classes and/or objects participating in this pattern are:
o Target (ChemicalCompound)
o defines the domain-specific interface that Client uses.
o Adapter (Compound)
o adapts the interface Adaptee to the Target interface.
o Adaptee (ChemicalDatabank)
o defines an existing interface that needs adapting.
o Client (AdapterApp)
o collaborates with objects conforming to the Target interface.

2.2.1.5 Sample code In C#


This structural code demonstrates the Adapter pattern which maps the
interface of one class onto another so that they can work together. These
incompatible classes may come from different libraries or frameworks.

// Adapter pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Adapter.Structural
{

// Mainapp test application

class MainApp
{
static void Main()
{
// Create adapter and place a request
Target target = new Adapter();
target.Request();

Version: 1.0
Side: 69
Project: Design Pattern

// Wait for user


Console.Read();
}
}

// "Target"

class Target
{
public virtual void Request()
{
Console.WriteLine("Called Target Request()");
}
}

// "Adapter"

class Adapter : Target


{
private Adaptee adaptee = new Adaptee();

public override void Request()


{
// Possibly do some other work
// and then call SpecificRequest
adaptee.SpecificRequest();
}
}

// "Adaptee"

class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Called SpecificRequest()");
}
}
}

Output
Called SpecificRequest()

2.2.1.6 Sample code In ABAP


This structural code demonstrates the Adapter pattern which maps the
interface of one class onto another so that they can work together. These
incompatible classes may come from different libraries or frameworks.

*&---------------------------------------------------------------------*
*& Report ZDP_ADAPTER_STRUCTURAL

Version: 1.0
Side: 70
Project: Design Pattern

*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_adapter_structural.

*----------------------------------------------------------------------*
* CLASS target DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS target DEFINITION.
PUBLIC SECTION.
METHODS:
request.
ENDCLASS. "target DEFINITION

*----------------------------------------------------------------------*
* CLASS target IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS target IMPLEMENTATION.
METHOD request.
WRITE: / 'Called Target Request()'.
ENDMETHOD. "request
ENDCLASS. "target IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS adaptee DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS adaptee DEFINITION.
PUBLIC SECTION.
METHODS:
specificrequest.
ENDCLASS. "adaptee DEFINITION

*----------------------------------------------------------------------*
* CLASS adaptee IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS adaptee IMPLEMENTATION.
METHOD specificrequest.
WRITE: / 'Called SpecificRequest()'.
ENDMETHOD. "specificrequest
ENDCLASS. "adaptee IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS adapter DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS adapter DEFINITION INHERITING FROM target.
PUBLIC SECTION.
METHODS:
constructor
,request REDEFINITION.
PRIVATE SECTION.
CLASS-DATA: adaptee TYPE REF TO adaptee.
ENDCLASS. "adapter DEFINITION

*----------------------------------------------------------------------*

Version: 1.0
Side: 71
Project: Design Pattern

* CLASS adapter IMPLEMENTATION


*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS adapter IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor.
CREATE OBJECT adaptee.
ENDMETHOD. "constructor

METHOD request.
CALL METHOD adaptee->specificrequest( ).
ENDMETHOD. "request
ENDCLASS. "adapter IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
data: mytarget type REF TO target
,myadapter TYPE REF TO adapter
.
* create adapter and place request
create OBJECT myadapter.

* Upcasting
mytarget = myadapter.
call METHOD mytarget->request( ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT:
---------

Called SpecificRequest()

2.2.1.7 Sample code In C#


This real-world code demonstrates the use of a legacy chemical databank.
Chemical compound objects access the databank through an Adapter interface

// Adapter pattern -- Real World example

Version: 1.0
Side: 72
Project: Design Pattern

using System;

namespace DoFactory.GangOfFour.Adapter.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Non-adapted chemical compound
Compound stuff = new Compound("Unknown");
stuff.Display();

// Adapted chemical compounds


Compound water = new RichCompound("Water");
water.Display();

Compound benzene = new RichCompound("Benzene");


benzene.Display();

Compound alcohol = new RichCompound("Alcohol");


alcohol.Display();

// Wait for user


Console.Read();
}
}

// "Target"

class Compound
{
protected string name;
protected float boilingPoint;
protected float meltingPoint;
protected double molecularWeight;
protected string molecularFormula;

// Constructor
public Compound(string name)
{
this.name = name;
}

public virtual void Display()


{
Console.WriteLine("\nCompound: {0} ------ ", name);
}
}

// "Adapter"

class RichCompound : Compound


{

Version: 1.0
Side: 73
Project: Design Pattern

private ChemicalDatabank bank;

// Constructor
public RichCompound(string name) : base(name)
{
}

public override void Display()


{
// Adaptee
bank = new ChemicalDatabank();
boilingPoint = bank.GetCriticalPoint(name, "B");
meltingPoint = bank.GetCriticalPoint(name, "M");
molecularWeight = bank.GetMolecularWeight(name);
molecularFormula = bank.GetMolecularStructure(name);

base.Display();
Console.WriteLine(" Formula: {0}", molecularFormula);
Console.WriteLine(" Weight : {0}", molecularWeight);
Console.WriteLine(" Melting Pt: {0}", meltingPoint);
Console.WriteLine(" Boiling Pt: {0}", boilingPoint);
}
}

// "Adaptee"

class ChemicalDatabank
{
// The Databank 'legacy API'
public float GetCriticalPoint(string compound, string point)
{
float temperature = 0.0F;

// Melting Point
if (point == "M")
{
switch (compound.ToLower())
{
case "water" : temperature = 0.0F; break;
case "benzene" : temperature = 5.5F; break;
case "alcohol" : temperature = -114.1F; break;
}
}
// Boiling Point
else
{
switch (compound.ToLower())
{
case "water" : temperature = 100.0F; break;
case "benzene" : temperature = 80.1F; break;
case "alcohol" : temperature = 78.3F; break;
}
}
return temperature;
}

Version: 1.0
Side: 74
Project: Design Pattern

public string GetMolecularStructure(string compound)


{
string structure = "";

switch (compound.ToLower())
{
case "water" : structure = "H20"; break;
case "benzene" : structure = "C6H6"; break;
case "alcohol" : structure = "C2H6O2"; break;
}
return structure;
}

public double GetMolecularWeight(string compound)


{
double weight = 0.0;
switch (compound.ToLower())
{
case "water" : weight = 18.015; break;
case "benzene" : weight = 78.1134; break;
case "alcohol" : weight = 46.0688; break;
}
return weight;
}
}
}

Output
Compound: Unknown ------

Compound: Water ------


Formula: H20
Weight : 18.015
Melting Pt: 0
Boiling Pt: 100

Compound: Benzene ------


Formula: C6H6
Weight : 78.1134
Melting Pt: 5.5
Boiling Pt: 80.1

Compound: Alcohol ------


Formula: C2H6O2
Weight : 46.0688
Melting Pt: -114.1
Boiling Pt: 78.3

2.2.1.8 Sample code In ABAP


This real-world code demonstrates the use of a legacy chemical databank.
Chemical compound objects access the databank through an Adapter interface

*&---------------------------------------------------------------------*
*& Report ZDP_ADAPTER_REALWORLD
*&

Version: 1.0
Side: 75
Project: Design Pattern

*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_adapter_zdp_adapter_realworld.
TYPES:
_float TYPE float
,_double TYPE p LENGTH 4 DECIMALS 4
,_string TYPE string.

*----------------------------------------------------------------------*
* CLASS compound DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compound DEFINITION.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE _string
,display.
PROTECTED SECTION.
DATA: name TYPE _string
,boilingpoint TYPE _float
,meltingpoint TYPE _float
,molecularweight TYPE _double
,molecularformula TYPE _string
.
ENDCLASS. "compound DEFINITION

*----------------------------------------------------------------------*
* CLASS compound IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compound IMPLEMENTATION.
METHOD constructor.
me->name = name.
ENDMETHOD. "constructor

METHOD display.
WRITE: /, /2(30)'Compound: -----', name .
ENDMETHOD. "display

ENDCLASS. "compound IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS chemicaldatabank DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS chemicaldatabank DEFINITION.
PUBLIC SECTION.
METHODS:
getcriticalpoint
IMPORTING compound TYPE _string
point TYPE _string
RETURNING value(temperature) TYPE _float
,getmolecularstructure
IMPORTING compound TYPE _string
RETURNING value(structure) TYPE _string
,getmolecularweight
IMPORTING compound TYPE _string
RETURNING value(weight) TYPE _double
.
ENDCLASS. "adaptee DEFINITION

Version: 1.0
Side: 76
Project: Design Pattern

*----------------------------------------------------------------------*
* CLASS chemicaldatabank IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS chemicaldatabank IMPLEMENTATION.
METHOD getcriticalpoint.
CLEAR temperature .
CASE point.
WHEN 'M'.
CASE compound.
WHEN 'Water'.
temperature = '0.0'.
WHEN 'Benzene'.
temperature = '5.5'.
WHEN 'Alcohol'.
temperature = '-114.1'.
WHEN OTHERS.
ENDCASE.
WHEN OTHERS.
CASE compound.
WHEN 'Water'.
temperature = '100.0'.
WHEN 'Benzene'.
temperature = '80.1'.
WHEN 'Alcohol'.
temperature = '78.3'.
WHEN OTHERS.
temperature = temperature.
ENDCASE.
ENDCASE.
ENDMETHOD. "specificrequest
METHOD getmolecularstructure.
CLEAR structure .
CASE compound.
WHEN 'Water'.
structure = 'H2O'.
WHEN 'Benzene'.
structure = 'C6H6'.
WHEN 'Alcohol'.
structure = 'C2H6O2'.
WHEN OTHERS.
structure = structure.
ENDCASE.
ENDMETHOD. "getmolecularstructure

METHOD getmolecularweight.
CLEAR weight.
CASE compound.
WHEN 'Water'.
weight = '18.015'.
WHEN 'Benzene'.
weight = '78.1134'.
WHEN 'Alcohol'.
weight = '46.0688'.
WHEN OTHERS.
weight = weight.
ENDCASE.

ENDMETHOD. "getmolecularweight

ENDCLASS. "adaptee IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS Richcompound DEFINITION
*----------------------------------------------------------------------*

Version: 1.0
Side: 77
Project: Design Pattern

*
*----------------------------------------------------------------------*
CLASS richcompound DEFINITION INHERITING FROM compound.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,display REDEFINITION.
PRIVATE SECTION.
DATA:
bank TYPE REF TO chemicaldatabank.

ENDCLASS. "Richcompound DEFINITION

*----------------------------------------------------------------------*
* CLASS Richcompound IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS richcompound IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor
EXPORTING
name = name.
CREATE OBJECT bank.
ENDMETHOD. "constructor

METHOD display.
boilingpoint = bank->getcriticalpoint( compound = me->name
point = 'B' ).
meltingpoint = bank->getcriticalpoint( compound = me->name
point = 'M' ).
molecularweight = bank->getmolecularweight( me->name ).
molecularformula = bank->getmolecularstructure( me->name ).

CALL METHOD super->display( ).


WRITE: /5(30) 'Formula:' , molecularformula.
WRITE: /5(30) 'Weight:' , molecularweight .
WRITE: /5(30) 'Melting Pt:', meltingpoint DECIMALS 2 EXPONENT 0.
WRITE: /5(30) 'Boiling Pt:', boilingpoint DECIMALS 2 EXPONENT 0.

ENDMETHOD. "request
ENDCLASS. "Richcompound IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: mystuff TYPE REF TO compound
,mywater TYPE REF TO richcompound
,mybenzene TYPE REF TO richcompound
,myalcohol TYPE REF TO richcompound
.

Version: 1.0
Side: 78
Project: Design Pattern

* create Richcompound and place request


CREATE OBJECT mystuff EXPORTING name = 'Unknown'.
mystuff->display( ).

CREATE OBJECT mywater EXPORTING name = 'Water'.


mywater->display( ).

CREATE OBJECT mybenzene EXPORTING name = 'Benzene'.


mybenzene->display( ).

CREATE OBJECT myalcohol EXPORTING name = 'Alcohol'.


myalcohol->display( ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT:
--------

Compound: Unknown

Compound: Water
Formula: H2O
Weight: 18,0150
Melting Pt: 0,00
Boiling Pt: 100,00

Compound: Benzene
Formula: C6H6
Weight: 78,1134
Melting Pt: 5,50
Boiling Pt: 80,10

Compound: Alcohol
Formula: C2H6O2
Weight: 46,0688
Melting Pt: -114,10
Boiling Pt: 78,30

2.2.1.9 Sample code In ABAP using interfaces


This real-world code demonstrates the use of a an Adapter interface. Wh have
three grafihical elements the square, triangle and circle and the client want to
get the elements area by using the same interface GET_AREA().
*&---------------------------------------------------------------------*
*& Report ZDP_ADAPTER_EKSEMPEL
*&
*&---------------------------------------------------------------------*
*& Exampel of the use of ADAPTER patterns. In this application we have
*& 3 different classes circle, triangle and square. These 3 grafical
*& elements obviously have different attributes and behavior. But from
*& the clients point of view, it would make sence to ask each element
*& what the area was. In abap this is best done through interfaces. Here
*& we need the interface GET_AREAL() as a commond method for all three
*& grafihical elements. In the example I also uses aliases to make the
*& use more simpel from the element implementation.
*&---------------------------------------------------------------------*

Version: 1.0
Side: 79
Project: Design Pattern

REPORT zdp_adapter_eksempel.

*----------------------------------------------------------------------*
* INTERFACE lif_figur
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_figur.
METHODS:
get_areal RETURNING value(areal) TYPE i.
ENDINTERFACE. "lif_figur

*----------------------------------------------------------------------*
* CLASS lcl_cirkel DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_cirkel DEFINITION.
PUBLIC SECTION.
DATA: radius TYPE i.
INTERFACES:
lif_figur.
ALIASES get_areal FOR lif_figur~get_areal.
METHODS:
constructor IMPORTING r TYPE i.
ENDCLASS. "lcl_cirkel DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_cirkel IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_cirkel IMPLEMENTATION.
METHOD constructor.
me->radius = r.
ENDMETHOD. "constructor
METHOD get_areal.
DATA: pi TYPE f.
pi = 22 / 7.
areal = ( me->radius ** 2 ) * pi.
ENDMETHOD. "get_areal
ENDCLASS. "lcl_cirkel IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_firkant DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_firkant DEFINITION.
PUBLIC SECTION.
DATA: laengde TYPE i
,bredde TYPE i.
INTERFACES:
lif_figur.
ALIASES get_areal FOR lif_figur~get_areal.
METHODS:
constructor IMPORTING l TYPE i b TYPE i.
ENDCLASS. "lcl_firkant DEFINITION

Version: 1.0
Side: 80
Project: Design Pattern

*----------------------------------------------------------------------*
* CLASS lcl_firkant IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_firkant IMPLEMENTATION.
METHOD constructor.
me->laengde = l.
me->bredde = b.
ENDMETHOD. "constructor
METHOD get_areal.
areal = me->laengde * me->bredde.
ENDMETHOD. "get_areal
ENDCLASS. "lcl_firkant IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_trekant DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_trekant DEFINITION.
PUBLIC SECTION.
DATA: hojde TYPE i
,grundlinie TYPE i.
INTERFACES:
lif_figur.
ALIASES get_areal FOR lif_figur~get_areal.
METHODS:
constructor IMPORTING h TYPE i g TYPE i.
ENDCLASS. "lcl_trekant DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_trekant IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_trekant IMPLEMENTATION.
METHOD constructor.
me->hojde = h.
me->grundlinie = g.
ENDMETHOD. "constructor
METHOD get_areal.
areal = ( me->hojde / 2 ) * me->grundlinie.
ENDMETHOD. "get_areal
ENDCLASS. "lcl_trekant IMPLEMENTATION

*----------------------------------------------------------
* CLASS lcl_application DEFINITION
* Pattern: SINGLETON
* Why: Definition create private ensures that nobody outside the
* class can create instances unless the class-method run()
* is activated and this method checks if an instance has
* allready been created.
*----------------------------------------------------------
CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.

Version: 1.0
Side: 81
Project: Design Pattern

DATA: io_name TYPE string.


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().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA:
o_cirkel TYPE REF TO lcl_cirkel
,o_firkant TYPE REF TO lcl_firkant
,o_trekant TYPE REF TO lcl_trekant
,areal TYPE i
.

* Først danner vi objekt referencerne på de enkelte figurer


CREATE OBJECT o_cirkel EXPORTING r = 24.
CREATE OBJECT o_trekant EXPORTING h = 2 g = 4.
CREATE OBJECT o_firkant EXPORTING l = 4 b = 5.

* Sa beder vi objekterne om at fortælle deres areal.


areal = o_cirkel->get_areal( ).
WRITE:/ 'Cirklens areal er ', areal.

areal = o_trekant->get_areal( ).
WRITE:/ 'Trekantens areal er ', areal.

areal = o_firkant->get_areal( ).
WRITE:/ 'Firkantens areal er ', areal.

ENDMETHOD. "constructor

ENDCLASS. "lcl_application IMPLEMENTATION

START-OF-SELECTION.

Version: 1.0
Side: 82
Project: Design Pattern

lcl_application=>run( ).

2.2.2 Bridge
Separates an object’s interface from its implementation

2.2.2.1 Definition
The bridge pattern is a design pattern used in software engineering which is
meant to "decouple an abstraction from its implementation so that the two can
vary independently" (Gamma et al.).

The bridge uses encapsulation, aggregation, and can use inheritance to


separate responsibilities into different classes.

When a class varies often, the features of object-oriented programming


become very useful because changes to a program's code can be made easily
with minimal prior knowledge about the program. The bridge pattern is useful
when not only the class itself varies often but also what the class does. The
class itself can be thought of as the abstraction and what the class can do as
the implementation.

Variant: The implementation can be decoupled even more by deferring the


presence of the implementation to the point where the abstraction is utilized
(as illustrated by the Visual Prolog example below).

2.2.2.2 Common Use


Shape abstraction
When the abstraction and implementation are separated, they can vary
independently. Consider the abstraction of shapes. There are many types of
shapes, each with its own properties. And there are things that all shapes do.
One thing all shapes can do is draw themselves. However, drawing graphics to
a screen can sometimes be dependent on different graphics implementations
or operating systems.

Shapes have to be able to be drawn on many types of systems. Having the


shape itself implement them all, or modifying the shape class to work with
different architectures is not practical. The bridge helps by allowing the
creation of new classes that provide the drawing implementation. The abstract
class, shape, provides methods for getting the size or properties of a shape.
The implementation class, drawing, provides an interface for drawing graphics.
If a new shape needs to be created or there is a new graphics API to be drawn
on, then it is very easy to add a new class that implements the needed
features.[

Car abstraction

Version: 1.0
Side: 83
Project: Design Pattern

Imagine two types of cars (the abstraction), a Jaguar and a Mercedes (both
are Refinements of the Abstraction). The Abstraction defines that a Car has
features such as tires and an engine. Refinements of the Abstraction declare
what specific kind of tires and engine it has.

Finally, there are two types of road. The road is the Implementor (see image
below). A highway and an interstate highway are the Implementation Details.
Any car refinement needs to be able to drive on any type of road; this concept
is what the Bridge Pattern is all about.

2.2.2.3 UML class diagram

class diagram of the bridge design pattern, created by Nvineeth using dpatoolkit

2.2.2.4 Participants
2.2.2.5 Sample code In C#

2.2.3 Composite
A tree structure of simple and composite objects

2.2.3.1 Definition
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat
individual objects and compositions of objects uniformly.

The example could be more accurate, as the leaf can neither remove or add, and therefore these methods
should not be part of the component butmoved to the composite, the only common methods are the
constructor and display.

Version: 1.0
Side: 84
Project: Design Pattern

2.2.3.2 UML class diagram

2.2.3.3 Participants
The classes and/or objects participating in this pattern are:
• Component (DrawingElement)
o declares the interface for objects in the composition. implements
default behavior for the interface common to all classes, as
appropriate. declares an interface for accessing and managing its
child components. (optional) defines an interface for accessing a
component's parent in the recursive structure, and implements it if
that's appropriate.
• Leaf (PrimitiveElement)
o represents leaf objects in the composition. A leaf has no children.
defines behavior for primitive objects in the composition.
• Composite (CompositeElement)
o defines behavior for components having children. stores child
components. implements child-related operations in the
Component interface.
• Client (CompositeApp)
o manipulates objects in the composition through the Component
interface.

2.2.3.4 Sample code In C#


This structural code demonstrates the Composite pattern which allows the
creation of a tree structure in which individual nodes are accessed uniformly
whether they are leaf nodes or branch (composite) nodes.

Version: 1.0
Side: 85
Project: Design Pattern

// Composite pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Composite.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
// Create a tree structure
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));

Composite comp = new Composite("Composite X");


comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));

root.Add(comp);
root.Add(new Leaf("Leaf C"));

// Add and remove a leaf


Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);

// Recursively display tree


root.Display(1);

// Wait for user


Console.Read();
}
}

// "Component"

abstract class Component


{
protected string name;

// Constructor
public Component(string name)
{
this.name = name;
}

public abstract void Add(Component c);


public abstract void Remove(Component c);
public abstract void Display(int depth);
}

Version: 1.0
Side: 86
Project: Design Pattern

// "Composite"

class Composite : Component


{
private ArrayList children = new ArrayList();

// Constructor
public Composite(string name) : base(name)
{
}

public override void Add(Component component)


{
children.Add(component);
}

public override void Remove(Component component)


{
children.Remove(component);
}

public override void Display(int depth)


{
Console.WriteLine(new String('-', depth) + name);

// Recursively display child nodes


foreach (Component component in children)
{
component.Display(depth + 2);
}
}
}

// "Leaf"

class Leaf : Component


{
// Constructor
public Leaf(string name) : base(name)
{
}

public override void Add(Component c)


{
Console.WriteLine("Cannot add to a leaf");
}

public override void Remove(Component c)


{
Console.WriteLine("Cannot remove from a leaf");
}

public override void Display(int depth)


{
Console.WriteLine(new String('-', depth) + name);
}

Version: 1.0
Side: 87
Project: Design Pattern

}
}

Output
-root
---Leaf A
---Leaf B
---Composite X
-----Leaf XA
-----Leaf XB
---Leaf C

2.2.3.5 Sample code In ABAP


This structural code demonstrates the Composite pattern which allows the
creation of a tree structure in which individual nodes are accessed uniformly
whether they are leaf nodes or branch (composite) nodes.

*&---------------------------------------------------------------------*
*& Report ZDP_COMPOSITE_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_composite_structural.

*----------------------------------------------------------------------*
* CLASS component DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS component DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,add ABSTRACT IMPORTING component TYPE REF TO component
,remove ABSTRACT IMPORTING component TYPE REF TO component
,display ABSTRACT IMPORTING depth TYPE i
.
PROTECTED SECTION.
DATA: name TYPE string.
ENDCLASS. "component DEFINITION

*----------------------------------------------------------------------*
* CLASS component IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS component IMPLEMENTATION.
METHOD constructor.
me->name = name.
ENDMETHOD. "constructor
ENDCLASS. "component IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS composite DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS composite DEFINITION INHERITING FROM component.
PUBLIC SECTION.

Version: 1.0
Side: 88
Project: Design Pattern

METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(composite) TYPE REF TO composite .
PRIVATE SECTION.
DATA children TYPE TABLE OF REF TO component.
ENDCLASS. "composite DEFINITION
*----------------------------------------------------------------------*
* CLASS composite IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS composite IMPLEMENTATION.
METHOD add.
INSERT component INTO TABLE children.
ENDMETHOD. "add

METHOD remove.
FIELD-SYMBOLS <fs> TYPE REF TO component.
data: index type sy-tabix.

LOOP AT children ASSIGNING <fs>.


index = sy-tabix.
IF <fs> = component.
EXIT.
ENDIF.
ENDLOOP.
IF sy-subrc = 0.
DELETE children INDEX index.
ENDIF.
ENDMETHOD. "remove

METHOD display.
FIELD-SYMBOLS <fs> TYPE REF TO component.
DATA mydepth TYPE i.

write: /.
do depth times.
write '-'.
enddo.
WRITE: me->name.

mydepth = depth + 1.
LOOP AT children ASSIGNING <fs>.
<fs>->display( EXPORTING depth = mydepth ).
ENDLOOP.
ENDMETHOD. "display

METHOD new.
CREATE OBJECT composite EXPORTING name = name.
ENDMETHOD. "new

ENDCLASS. "composite IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS leaf DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS leaf DEFINITION INHERITING FROM component.
PUBLIC SECTION.

Version: 1.0
Side: 89
Project: Design Pattern

METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(leaf) TYPE REF TO leaf .
ENDCLASS. "leaf DEFINITION
*----------------------------------------------------------------------*
* CLASS leaf IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS leaf IMPLEMENTATION.
METHOD add.
WRITE: / 'Cannot add to a leaf'.
ENDMETHOD. "add
METHOD remove.
WRITE: / 'Cannot remove from a leaf'.
ENDMETHOD. "remove
METHOD display.
write: /.
do depth times.
write '-'.
enddo.
WRITE: me->name.
ENDMETHOD. "display
METHOD new.
CREATE OBJECT leaf EXPORTING name = name.
ENDMETHOD. "new
ENDCLASS. "leaf IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: myroot TYPE REF TO composite
,myleaf TYPE REF TO leaf
,mycomposite TYPE REF TO composite
.
myroot = composite=>new('root').

myleaf = leaf=>new('Leaf A'). myroot->add( myleaf ).


myleaf = leaf=>new('Leaf B'). myroot->add( myleaf ).

mycomposite = composite=>new('Composite X').


myleaf = leaf=>new('Leaf XA'). mycomposite->add( myleaf ).
myleaf = leaf=>new('Leaf XB'). mycomposite->add( myleaf ).

myroot->add( mycomposite ).
myleaf = leaf=>new('Leaf C'). myroot->add( myleaf ).

Version: 1.0
Side: 90
Project: Design Pattern

myleaf = leaf=>new('Leaf D'). myroot->add( myleaf ).


myroot->remove( myleaf ).

myroot->display( 1 ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT:
- root
- - Leaf A
- - Leaf B
- - Composite X
- - - Leaf XA
- - - Leaf XB
- - Leaf C

2.2.3.6 Sample code In C#


This real-world code demonstrates the Composite pattern used in building a
graphical tree structure made up of primitive nodes (lines, circles, etc) and
composite nodes (groups of drawing elements that make up more complex
elements).

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Composite.RealWorld
{

// Mainapp test application

class MainApp
{
static void Main()
{
// Create a tree structure
CompositeElement root =
new CompositeElement("Picture");
root.Add(new PrimitiveElement("Red Line"));
root.Add(new PrimitiveElement("Blue Circle"));
root.Add(new PrimitiveElement("Green Box"));

CompositeElement comp =
new CompositeElement("Two Circles");
comp.Add(new PrimitiveElement("Black Circle"));
comp.Add(new PrimitiveElement("White Circle"));
root.Add(comp);

// Add and remove a PrimitiveElement


PrimitiveElement pe =
new PrimitiveElement("Yellow Line");
root.Add(pe);
root.Remove(pe);

// Recursively display nodes

Version: 1.0
Side: 91
Project: Design Pattern

root.Display(1);

// Wait for user


Console.Read();
}
}

// "Component" Treenode

abstract class DrawingElement


{
protected string name;

// Constructor
public DrawingElement(string name)
{
this.name = name;
}

public abstract void Add(DrawingElement d);


public abstract void Remove(DrawingElement d);
public abstract void Display(int indent);
}

// "Leaf"

class PrimitiveElement : DrawingElement


{
// Constructor
public PrimitiveElement(string name) : base(name)
{
}

public override void Add(DrawingElement c)


{
Console.WriteLine(
"Cannot add to a PrimitiveElement");
}

public override void Remove(DrawingElement c)


{
Console.WriteLine(
"Cannot remove from a PrimitiveElement");
}

public override void Display(int indent)


{
Console.WriteLine(
new String('-', indent) + " " + name);
}
}

// "Composite"

class CompositeElement : DrawingElement


{
private ArrayList elements = new ArrayList();

// Constructor
public CompositeElement(string name) : base(name)
{
}

public override void Add(DrawingElement d)


{
elements.Add(d);

Version: 1.0
Side: 92
Project: Design Pattern

public override void Remove(DrawingElement d)


{
elements.Remove(d);
}

public override void Display(int indent)


{
Console.WriteLine(new String('-', indent) +
"+ " + name);

// Display each child element on this node


foreach (DrawingElement c in elements)
{
c.Display(indent + 2);
}
}
}
}

Output
-+ Picture
--- Red Line
--- Blue Circle
--- Green Box
---+ Two Circles
----- Black Circle
----- White Circle

2.2.3.7 Sample code In ABAP


This real-world code demonstrates the Composite pattern used in building a
graphical tree structure made up of primitive nodes (lines, circles, etc) and
composite nodes (groups of drawing elements that make up more complex
elements).

*&---------------------------------------------------------------------*
*& Report ZDP_COMPOSITE_REALWORLD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_composite_realworld.

*----------------------------------------------------------------------*
* CLASS DrawingElement DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS drawingelement DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,add ABSTRACT IMPORTING drawingelement TYPE REF TO drawingelement
,remove ABSTRACT IMPORTING drawingelement TYPE REF TO drawingelement
,display ABSTRACT IMPORTING indent TYPE i
.
PROTECTED SECTION.

Version: 1.0
Side: 93
Project: Design Pattern

DATA: name TYPE string.


ENDCLASS. "DrawingElement DEFINITION

*----------------------------------------------------------------------*
* CLASS DrawingElement IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS drawingelement IMPLEMENTATION.
METHOD constructor.
me->name = name.
ENDMETHOD. "constructor
ENDCLASS. "DrawingElement IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS compositeElement DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compositeelement DEFINITION INHERITING FROM drawingelement.
PUBLIC SECTION.
METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(compositeelement) TYPE REF TO compositeelement .
PRIVATE SECTION.
DATA elements TYPE TABLE OF REF TO drawingelement.
ENDCLASS. "compositeElement DEFINITION

*----------------------------------------------------------------------*
* CLASS compositeElement IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compositeelement IMPLEMENTATION.
METHOD add.
INSERT drawingelement INTO TABLE elements.
ENDMETHOD. "add

METHOD remove.
FIELD-SYMBOLS <fs> TYPE REF TO drawingelement.
DATA: index TYPE sy-tabix.

LOOP AT elements ASSIGNING <fs>.


index = sy-tabix.
IF <fs> = drawingelement.
EXIT.
ENDIF.
ENDLOOP.
IF sy-subrc = 0.
DELETE elements INDEX index.
ENDIF.
ENDMETHOD. "remove

METHOD display.
FIELD-SYMBOLS <fs> TYPE REF TO drawingelement.
DATA myindent TYPE i.

WRITE: /.
DO indent TIMES.
WRITE '-'.
ENDDO.

Version: 1.0
Side: 94
Project: Design Pattern

WRITE: '+' , me->name.

myindent = indent + 2.
LOOP AT elements ASSIGNING <fs>.
<fs>->display( EXPORTING indent = myindent ).
ENDLOOP.
ENDMETHOD. "display

METHOD new.
CREATE OBJECT compositeelement EXPORTING name = name.
ENDMETHOD. "new

ENDCLASS. "compositeElement IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS PrimitiveElement DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS primitiveelement DEFINITION INHERITING FROM drawingelement.
PUBLIC SECTION.
METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(primitiveelement) TYPE REF TO primitiveelement .
ENDCLASS. "PrimitiveElement DEFINITION

*----------------------------------------------------------------------*
* CLASS PrimitiveElement IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS primitiveelement IMPLEMENTATION.
METHOD add.
WRITE: / 'Cannot add to a PrimitiveElement'.
ENDMETHOD. "add
METHOD remove.
WRITE: / 'Cannot remove from a PrimitiveElement'.
ENDMETHOD. "remove
METHOD display.
WRITE: /.
DO indent TIMES.
WRITE '-'.
ENDDO.
WRITE: me->name.
ENDMETHOD. "display
METHOD new.
CREATE OBJECT primitiveelement EXPORTING name = name.
ENDMETHOD. "new
ENDCLASS. "PrimitiveElement IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

Version: 1.0
Side: 95
Project: Design Pattern

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: myroot TYPE REF TO compositeelement
,myprimitiveelement TYPE REF TO primitiveelement
,mycompositeelement TYPE REF TO compositeelement
.
myroot = compositeelement=>new('Picture').

myprimitiveelement = primitiveelement=>new('Red Line'). myroot->add(


myprimitiveelement ).
myprimitiveelement = primitiveelement=>new('Blue Circle'). myroot->add(
myprimitiveelement ).
myprimitiveelement = primitiveelement=>new('Gree Box'). myroot->add(
myprimitiveelement ).

mycompositeelement = compositeelement=>new('Two Circles').


myprimitiveelement = primitiveelement=>new('Black Circle'). mycompositeelement->add(
myprimitiveelement ).
myprimitiveelement = primitiveelement=>new('White Circle'). mycompositeelement->add(
myprimitiveelement ).
myroot->add( mycompositeelement ).

myprimitiveelement = primitiveelement=>new('Yellow Line'). myroot->add(


myprimitiveelement ).
myroot->remove( myprimitiveelement ).

myroot->display( 1 ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT:

- + Picture
- - - Red Line
- - - Blue Circle
- - - Gree Box
- - - + Two Circles
- - - - - Black Circle
- - - - - White Circle

2.2.4 Decorator
Add responsibilities to objects dynamically

2.2.4.1 Definition
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to
subclassing for extending functionality.

Version: 1.0
Side: 96
Project: Design Pattern

2.2.4.2 UML class diagram

2.2.4.3 Participants
The classes and/or objects participating in this pattern are:

• Component (LibraryItem)
o defines the interface for objects that can have responsibilities added to them dynamically.
• ConcreteComponent (Book, Video)
o defines an object to which additional responsibilities can be attached.
• Decorator (Decorator)
o maintains a reference to a Component object and defines an interface that conforms to
Component's interface.
• ConcreteDecorator (Borrowable)
o adds responsibilities to the component.

2.2.4.4 Sample code In C#


This structural code demonstrates the Decorator pattern which dynamically
adds extra functionality to an existing object.

// Decorator pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Decorator.Structural
{

Version: 1.0
Side: 97
Project: Design Pattern

// MainApp test application

class MainApp
{
static void Main()
{
// Create ConcreteComponent and two Decorators
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();

// Link decorators
d1.SetComponent(c);
d2.SetComponent(d1);

d2.Operation();

// Wait for user


Console.Read();
}
}

// "Component"

abstract class Component


{
public abstract void Operation();
}

// "ConcreteComponent"

class ConcreteComponent : Component


{
public override void Operation()
{
Console.WriteLine("ConcreteComponent.Operation()");
}
}

// "Decorator"

abstract class Decorator : Component


{
protected Component component;

public void SetComponent(Component component)


{
this.component = component;
}

public override void Operation()


{
if (component != null)
{
component.Operation();
}

Version: 1.0
Side: 98
Project: Design Pattern

}
}

// "ConcreteDecoratorA"

class ConcreteDecoratorA : Decorator


{
private string addedState;

public override void Operation()


{
base.Operation();
addedState = "New State";
Console.WriteLine("ConcreteDecoratorA.Operation()");
}
}

// "ConcreteDecoratorB"

class ConcreteDecoratorB : Decorator


{
public override void Operation()
{
base.Operation();
AddedBehavior();
Console.WriteLine("ConcreteDecoratorB.Operation()");
}

void AddedBehavior()
{
}
}
}

Output
ConcreteComponent.Operation()
ConcreteDecoratorA.Operation()
ConcreteDecoratorB.Operation()

2.2.4.5 Sample code In ABAP


This structural code demonstrates the Decorator pattern which dynamically
adds extra functionality to an existing object.
*&---------------------------------------------------------------------*
*& Report ZDP_DECORATOR_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_decorator_structural.

*----------------------------------------------------------------------*
* CLASS component DEFINITION
*----------------------------------------------------------------------*

Version: 1.0
Side: 99
Project: Design Pattern

*
*----------------------------------------------------------------------*
CLASS component DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
operation ABSTRACT.
ENDCLASS. "component DEFINITION

*----------------------------------------------------------------------*
* CLASS concretecomponent DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecomponent DEFINITION INHERITING FROM component.
PUBLIC SECTION.
METHODS:
operation REDEFINITION.
ENDCLASS. "concretecomponent DEFINITION

*----------------------------------------------------------------------*
* CLASS concretecomponent IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecomponent IMPLEMENTATION.
METHOD operation.
WRITE: / 'ConcreteComponent.Operation()'.
ENDMETHOD. "operation
ENDCLASS. "concretecomponent IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS decorator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS decorator DEFINITION INHERITING FROM component ABSTRACT.
PUBLIC SECTION.
METHODS:
setcomponent IMPORTING component TYPE REF TO component
,operation REDEFINITION
.
PROTECTED SECTION.
DATA: component TYPE REF TO component.
ENDCLASS. "decorator DEFINITION
*----------------------------------------------------------------------*
* CLASS decorator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS decorator IMPLEMENTATION.
METHOD setcomponent.
me->component = component.
ENDMETHOD. "setcomponent
METHOD operation.
IF NOT component IS INITIAL.
component->operation( ).
ENDIF.
ENDMETHOD. "operation
ENDCLASS. "decorator IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS concretedecoratora DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratora DEFINITION INHERITING FROM decorator.

Version: 1.0
Side: 100
Project: Design Pattern

PUBLIC SECTION.
METHODS:
operation REDEFINITION.
PRIVATE SECTION.
DATA:
addedstate TYPE string.
ENDCLASS. "concretedecoratora DEFINITION
*----------------------------------------------------------------------*
* CLASS concretedecoratora IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratora IMPLEMENTATION.
METHOD operation.
super->operation( ).
addedstate = 'New State'.
WRITE: / 'ConcreteDecoratorA.Operation()'.
ENDMETHOD. "operation
ENDCLASS. "concretedecoratora IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS concretedecoratorb DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratorb DEFINITION INHERITING FROM decorator.
PUBLIC SECTION.
METHODS:
operation REDEFINITION
,addedbehavior
.
ENDCLASS. "concretedecoratorb DEFINITION
*----------------------------------------------------------------------*
* CLASS concretedecoratorb IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratorb IMPLEMENTATION.
METHOD operation.
super->operation( ).
me->addedbehavior( ).
WRITE: / 'ConcreteDecoratorB.Operation()'.
ENDMETHOD. "operation
METHOD addedbehavior.
ENDMETHOD. "addedbehavior
ENDCLASS. "concretedecoratorb IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: c TYPE REF TO concretecomponent
,d1 TYPE REF TO concretedecoratora

Version: 1.0
Side: 101
Project: Design Pattern

,d2 TYPE REF TO concretedecoratorb


.
CREATE OBJECT c.
CREATE OBJECT d1.
CREATE OBJECT d2.

d1->setcomponent( c ).
d2->setcomponent( d1 ).
d2->operation( ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT:
---------------------
ConcreteComponent.Operation()
ConcreteDecoratorA.Operation()
ConcreteDecoratorB.Operation()

2.2.4.6 Sample code In C#


This real-world code demonstrates the Decorator pattern in which 'borrowable'
functionality is added to existing library items (books and videos).

// Decorator pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Decorator.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Create book
Book book = new Book ("Worley", "Inside ASP.NET", 10);
book.Display();

// Create video
Video video = new Video ("Spielberg", "Jaws", 23, 92);
video.Display();

// Make video borrowable, then borrow and display


Console.WriteLine("\nMaking video borrowable:");

Borrowable borrowvideo = new Borrowable(video);


borrowvideo.BorrowItem("Customer #1");
borrowvideo.BorrowItem("Customer #2");

borrowvideo.Display();

Version: 1.0
Side: 102
Project: Design Pattern

// Wait for user


Console.Read();
}
}

// "Component"

abstract class LibraryItem


{
private int numCopies;

// Property
public int NumCopies
{
get{ return numCopies; }
set{ numCopies = value; }
}

public abstract void Display();


}

// "ConcreteComponent"

class Book : LibraryItem


{
private string author;
private string title;

// Constructor
public Book(string author,string title,int numCopies)
{
this.author = author;
this.title = title;
this.NumCopies = numCopies;
}

public override void Display()


{
Console.WriteLine("\nBook ------ ");
Console.WriteLine(" Author: {0}", author);
Console.WriteLine(" Title: {0}", title);
Console.WriteLine(" # Copies: {0}", NumCopies);
}
}

// "ConcreteComponent"

class Video : LibraryItem


{
private string director;
private string title;
private int playTime;

// Constructor
public Video(string director, string title,

Version: 1.0
Side: 103
Project: Design Pattern

int numCopies, int playTime)


{
this.director = director;
this.title = title;
this.NumCopies = numCopies;
this.playTime = playTime;
}

public override void Display()


{
Console.WriteLine("\nVideo ----- ");
Console.WriteLine(" Director: {0}", director);
Console.WriteLine(" Title: {0}", title);
Console.WriteLine(" # Copies: {0}", NumCopies);
Console.WriteLine(" Playtime: {0}\n", playTime);
}
}

// "Decorator"

abstract class Decorator : LibraryItem


{
protected LibraryItem libraryItem;

// Constructor
public Decorator(LibraryItem libraryItem)
{
this.libraryItem = libraryItem;
}

public override void Display()


{
libraryItem.Display();
}
}

// "ConcreteDecorator"

class Borrowable : Decorator


{
protected ArrayList borrowers = new ArrayList();

// Constructor
public Borrowable(LibraryItem libraryItem)
: base(libraryItem)
{
}

public void BorrowItem(string name)


{
borrowers.Add(name);
libraryItem.NumCopies--;
}

public void ReturnItem(string name)


{

Version: 1.0
Side: 104
Project: Design Pattern

borrowers.Remove(name);
libraryItem.NumCopies++;
}

public override void Display()


{
base.Display();

foreach (string borrower in borrowers)


{
Console.WriteLine(" borrower: " + borrower);
}
}
}
}

Output
Book ------
Author: Worley
Title: Inside ASP.NET
# Copies: 10

Video -----
Director: Spielberg
Title: Jaws
# Copies: 23
Playtime: 92

Making video borrowable:

Video -----
Director: Spielberg
Title: Jaws
# Copies: 21
Playtime: 92

borrower: Customer #1
borrower: Customer #2

2.2.4.7 Sample code In ABAP


This real-world code demonstrates the Decorator pattern in which 'borrowable'
functionality is added to existing library items (books and videos).

*&---------------------------------------------------------------------*
*& Report ZDP_DECORATOR_REALWORLD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_decorator_realworld.

*----------------------------------------------------------------------*
* CLASS property DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*

Version: 1.0
Side: 105
Project: Design Pattern

CLASS property DEFINITION.


PUBLIC SECTION.
DATA: value TYPE i.
METHODS:
get RETURNING value(value) TYPE i
,set IMPORTING value TYPE i
.
ENDCLASS. "property DEFINITION

*----------------------------------------------------------------------*
* CLASS property IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS property IMPLEMENTATION.
METHOD get.
value = me->value.
ENDMETHOD. "get
METHOD set.
me->value = value.
ENDMETHOD. "set
ENDCLASS. "property IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS LibraryItem DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS libraryitem DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING numcopies TYPE i
,display ABSTRACT.

PROTECTED SECTION.
DATA: numcopies TYPE REF TO property.
ENDCLASS. "LibraryItem DEFINITION

*----------------------------------------------------------------------*
* CLASS libraryitem IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS libraryitem IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT me->numcopies.
me->numcopies->set( numcopies ).
ENDMETHOD. "constructor
ENDCLASS. "libraryitem IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS book DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS book DEFINITION INHERITING FROM libraryitem.
PUBLIC SECTION.
METHODS:
constructor IMPORTING author TYPE string
title TYPE string
numcopies TYPE i
,display REDEFINITION.
PRIVATE SECTION.
DATA:
author TYPE string
,title TYPE string

Version: 1.0
Side: 106
Project: Design Pattern

.
ENDCLASS. "book DEFINITION

*----------------------------------------------------------------------*
* CLASS book IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS book IMPLEMENTATION.
METHOD constructor.
super->constructor( numcopies ).
me->author = author.
me->title = title.
ENDMETHOD. "constructor

METHOD display.
DATA: numofcopies TYPE i.
WRITE: /, /2(20)'Book ---------------'.
WRITE: /5(15)'Author:........', author.
WRITE: /5(15)'Title:.........', title.
numofcopies = me->numcopies->get( ).
WRITE: /5(15)'# copies:......' , numofcopies .
ENDMETHOD. "display

ENDCLASS. "book IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS video DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS video DEFINITION INHERITING FROM libraryitem.
PUBLIC SECTION.
METHODS:
constructor IMPORTING director TYPE string
title TYPE string
numcopies TYPE i
playtime TYPE i
,display REDEFINITION.
PRIVATE SECTION.
DATA:
director TYPE string
,title TYPE string
,playtime TYPE i
.
ENDCLASS. "video DEFINITION

*----------------------------------------------------------------------*
* CLASS video IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS video IMPLEMENTATION.
METHOD constructor.
super->constructor( numcopies ).
me->director = director.
me->title = title.
me->playtime = playtime.
ENDMETHOD. "constructor

METHOD display.
DATA: numofcopies TYPE i.
WRITE: /, /2(20)'Video --------------'.
WRITE: /5(15)'Director:......', director.
WRITE: /5(15)'Title:.........', title.
numofcopies = me->numcopies->get( ).

Version: 1.0
Side: 107
Project: Design Pattern

WRITE: /5(15)'# copies:......' , numofcopies .


WRITE:/5(15)'Playtime:.......', playtime.
ENDMETHOD. "display

ENDCLASS. "video IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS decorator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS decorator DEFINITION INHERITING FROM libraryitem ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING libraryitem TYPE REF TO libraryitem
,display REDEFINITION
.
PROTECTED SECTION.
DATA: libraryitem TYPE REF TO libraryitem.

ENDCLASS. "decorator DEFINITION


*----------------------------------------------------------------------*
* CLASS decorator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS decorator IMPLEMENTATION.

METHOD constructor.
super->constructor( 1 ).
me->libraryitem = libraryitem.
ENDMETHOD. "constructor

METHOD display.
me->libraryitem->display( ).
ENDMETHOD. "display

ENDCLASS. "decorator IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS borrowable DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS borrowable DEFINITION INHERITING FROM decorator.
PUBLIC SECTION.
METHODS:
borrowitem IMPORTING name TYPE string
,returnitem IMPORTING name TYPE string
,display REDEFINITION
.
PROTECTED SECTION.
DATA borrowers TYPE TABLE OF string.

ENDCLASS. "borrowable DEFINITION

*----------------------------------------------------------------------*
* CLASS borrowable IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS borrowable IMPLEMENTATION.
METHOD borrowitem.
DATA: numofcopies TYPE i.
INSERT name INTO TABLE borrowers.

Version: 1.0
Side: 108
Project: Design Pattern

numofcopies = me->libraryitem->numcopies->get( ).
SUBTRACT 1 FROM numofcopies.
me->libraryitem->numcopies->set( numofcopies ).
ENDMETHOD. "borrowitem

METHOD returnitem.
ENDMETHOD. "returnitem
METHOD display.
DATA name TYPE string.

super->display( ).
WRITE: /.
LOOP AT borrowers INTO name.
WRITE: /10(10)'Borrower:.', name.
ENDLOOP.
ENDMETHOD. "display

ENDCLASS. "borrowable IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: book TYPE REF TO book
,video TYPE REF TO video
,borrowvideo TYPE REF TO borrowable
.
CREATE OBJECT book EXPORTING author = 'Worley'
title = 'Inside ASP.NET'
numcopies = 10.
book->display( ).

CREATE OBJECT video EXPORTING director = 'Spielberg'


title = 'Jaws'
numcopies = 23
playtime = 92.
video->display( ).

* make video borrowable, then borrow and display


WRITE: /, / 'Making Vide borrowable'.
CREATE OBJECT borrowvideo EXPORTING libraryitem = video.
borrowvideo->borrowitem( 'Customer #1' ).
borrowvideo->borrowitem( 'Customer #2' ).
borrowvideo->display( ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

Version: 1.0
Side: 109
Project: Design Pattern

OUTPUT:
-------

Book
Author:........ Worley
Title:......... Inside ASP.NET
# copies:...... 10

Video
Director:...... Spielberg
Title:......... Jaws
# copies:...... 23
Playtime:...... 92

Making Vide borrowable

Video
Director:...... Spielberg
Title:......... Jaws
# copies:...... 21
Playtime:...... 92

Borrower:. Customer #1
Borrower:. Customer #2

2.2.5 Facade
A single class that represents an entire subsystem

2.2.5.1 Definition
Provide a unified interface to a set of interfaces in a subsystem. Façade defines
a higher-level interface that makes the subsystem easier to use.

2.2.5.2 UML class diagram

2.2.5.3 Participants
The classes and/or objects participating in this pattern are:

Version: 1.0
Side: 110
Project: Design Pattern

• Facade (MortgageApplication)
o knows which subsystem classes are responsible for a request.
delegates client requests to appropriate subsystem objects.
• Subsystem classes (Bank, Credit, Loan)
o implement subsystem functionality. handle work assigned by the
Facade object. have no knowledge of the facade and keep no
reference to it.

2.2.5.4 Sample code In C#


This structural code demonstrates the Facade pattern which provides a
simplified and uniform interface to a large subsystem of classes.
// Facade pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Facade.Structural
{

// Mainapp test application

class MainApp
{
public static void Main()
{
Facade facade = new Facade();

facade.MethodA();
facade.MethodB();

// Wait for user


Console.Read();
}
}

// "Subsystem ClassA"

class SubSystemOne
{
public void MethodOne()
{
Console.WriteLine(" SubSystemOne Method");
}
}

// Subsystem ClassB"

class SubSystemTwo
{
public void MethodTwo()
{
Console.WriteLine(" SubSystemTwo Method");
}

Version: 1.0
Side: 111
Project: Design Pattern

// Subsystem ClassC"

class SubSystemThree
{
public void MethodThree()
{
Console.WriteLine(" SubSystemThree Method");
}
}

// Subsystem ClassD"

class SubSystemFour
{
public void MethodFour()
{
Console.WriteLine(" SubSystemFour Method");
}
}

// "Facade"

class Facade
{
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four;

public Facade()
{
one = new SubSystemOne();
two = new SubSystemTwo();
three = new SubSystemThree();
four = new SubSystemFour();
}

public void MethodA()


{
Console.WriteLine("\nMethodA() ---- ");
one.MethodOne();
two.MethodTwo();
four.MethodFour();
}

public void MethodB()


{
Console.WriteLine("\nMethodB() ---- ");
two.MethodTwo();
three.MethodThree();
}
}
}

Version: 1.0
Side: 112
Project: Design Pattern

Output
MethodA() ----
SubSystemOne Method
SubSystemTwo Method
SubSystemFour Method

MethodB() ----
SubSystemTwo Method
SubSystemThree Method

2.2.5.5 Sample code In ABAP


This structural code demonstrates the Facade pattern which provides a
simplified and uniform interface to a large subsystem of classes.
*&---------------------------------------------------------------------*
*& Report ZDP_FACADE_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_facade_structural.

*----------------------------------------------------------------------*
* CLASS subsystemone DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemone DEFINITION.
PUBLIC SECTION.
METHODS:
methodone.
ENDCLASS. "subsystemone DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemone IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemone IMPLEMENTATION.
METHOD methodone.
WRITE: / 'SubsystemOne Method'.
ENDMETHOD. "methodone
ENDCLASS. "subsystemone IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS subsystemtwo DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemtwo DEFINITION.
PUBLIC SECTION.
METHODS:
methodtwo.
ENDCLASS. "subsystemtwo DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemtwo IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*

Version: 1.0
Side: 113
Project: Design Pattern

CLASS subsystemtwo IMPLEMENTATION.


METHOD methodtwo.
WRITE: / 'SubsystemTwo Method'.
ENDMETHOD. "methodtwo
ENDCLASS. "subsystemtwo IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS subsystemThree DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemthree DEFINITION.
PUBLIC SECTION.
METHODS:
methodthree.
ENDCLASS. "subsystemThree DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemthree IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemthree IMPLEMENTATION.
METHOD methodthree.
WRITE: / 'SubsystemThree Method'.
ENDMETHOD. "methodthree
ENDCLASS. "subsystemthree IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS subsystemfour DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemfour DEFINITION.
PUBLIC SECTION.
METHODS:
methodfour.
ENDCLASS. "subsystemfour DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemfour IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemfour IMPLEMENTATION.
METHOD methodfour.
WRITE: / 'SubsystemFour Method'.
ENDMETHOD. "methodfour
ENDCLASS. "subsystemfour IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS facade DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS facade DEFINITION.
PUBLIC SECTION.
DATA:
one TYPE REF TO subsystemone
,two TYPE REF TO subsystemtwo
,three TYPE REF TO subsystemthree
,four TYPE REF TO subsystemfour
.
METHODS:
constructor
,methoda

Version: 1.0
Side: 114
Project: Design Pattern

,methodb
.
ENDCLASS. "facade DEFINITION
*----------------------------------------------------------------------*
* CLASS facade IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS facade IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT one.
CREATE OBJECT two.
CREATE OBJECT three.
CREATE OBJECT four.
ENDMETHOD. "constructor
METHOD methoda.
WRITE: /, / 'MethodA() ----'.
one->methodone( ).
two->methodtwo( ).
four->methodfour( ).
ENDMETHOD. "methoda
METHOD methodb.
WRITE: /, / 'MethodB() ----'.
two->methodtwo( ).
three->methodthree( ).
ENDMETHOD. "methodb
ENDCLASS. "facade IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: facade TYPE REF TO facade.

CREATE OBJECT facade.


facade->methoda( ).
facade->methodb( ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT:
---------

MethodA()
SubsystemOne Method
SubsystemTwo Method
SubsystemFour Method

Version: 1.0
Side: 115
Project: Design Pattern

MethodB()
SubsystemTwo Method
SubsystemThree Method

2.2.5.6 Sample code In C#

This real-world code demonstrates the Facade pattern as a MortgageApplication object


which provides a simplified interface to a large subsystem of classes measuring the
creditworthyness of an applicant.

// Facade pattern -- Real World example

using System;

namespace DoFactory.GangOfFour.Facade.RealWorld
{
// MainApp test application

class MainApp
{
static void Main()
{
// Facade
Mortgage mortgage = new Mortgage();

// Evaluate mortgage eligibility for customer


Customer customer = new Customer("Ann McKinsey");
bool eligable = mortgage.IsEligible(customer,125000);

Console.WriteLine("\n" + customer.Name +
" has been " + (eligable ? "Approved" : "Rejected"));

// Wait for user


Console.Read();
}
}

// "Subsystem ClassA"

class Bank
{
public bool HasSufficientSavings(Customer c, int amount)
{
Console.WriteLine("Check bank for " + c.Name);
return true;
}
}

// "Subsystem ClassB"

class Credit
{
public bool HasGoodCredit(Customer c)

Version: 1.0
Side: 116
Project: Design Pattern

{
Console.WriteLine("Check credit for " + c.Name);
return true;
}
}

// "Subsystem ClassC"

class Loan
{
public bool HasNoBadLoans(Customer c)
{
Console.WriteLine("Check loans for " + c.Name);
return true;
}
}

class Customer
{
private string name;

// Constructor
public Customer(string name)
{
this.name = name;
}

// Property
public string Name
{
get{ return name; }
}
}

// "Facade"

class Mortgage
{
private Bank bank = new Bank();
private Loan loan = new Loan();
private Credit credit = new Credit();

public bool IsEligible(Customer cust, int amount)


{
Console.WriteLine("{0} applies for {1:C} loan\n",
cust.Name, amount);

bool eligible = true;

// Check creditworthyness of applicant


if (!bank.HasSufficientSavings(cust, amount))
{
eligible = false;
}
else if (!loan.HasNoBadLoans(cust))
{

Version: 1.0
Side: 117
Project: Design Pattern

eligible = false;
}
else if (!credit.HasGoodCredit(cust))
{
eligible = false;
}

return eligible;
}
}
}

Output
Ann McKinsey applies for $125,000.00 loan

Check bank for Ann McKinsey


Check loans for Ann McKinsey
Check credit for Ann McKinsey

Ann McKinsey has been Approved

2.2.5.7 Sample code In ABAP

This real-world code demonstrates the Facade pattern as a


MortgageApplication object which provides a simplified interface to a large
subsystem of classes measuring the creditworthyness of an applicant.
*&---------------------------------------------------------------------*
*& Report ZDP_FACADE_REALWORLD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_facade_realworld.

*----------------------------------------------------------------------*
* CLASS customer DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS customer DEFINITION.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,getname RETURNING value(name) TYPE string
.
PRIVATE SECTION.
DATA: name TYPE string.

ENDCLASS. "customer DEFINITION


*----------------------------------------------------------------------*
* CLASS customer IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*

Version: 1.0
Side: 118
Project: Design Pattern

CLASS customer IMPLEMENTATION.


METHOD constructor.
me->name = name.
ENDMETHOD. "constructor

METHOD getname.
name = me->name.
ENDMETHOD. "getname
ENDCLASS. "customer IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS bank DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS bank DEFINITION.
PUBLIC SECTION.
METHODS:
hassufficientsavings
IMPORTING
customer TYPE REF TO customer
amount TYPE i
RETURNING value(val) TYPE boolean
.
ENDCLASS. "bank DEFINITION
*----------------------------------------------------------------------*
* CLASS bank IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS bank IMPLEMENTATION.
METHOD hassufficientsavings.
DATA: myname TYPE string.
myname = customer->getname( ).
WRITE: / 'Check bank for ', myname.
val = 'X'. "~TRUE
ENDMETHOD. "hassufficientsavings
ENDCLASS. "bank IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS credit DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS credit DEFINITION.
PUBLIC SECTION.
METHODS:
hasgoodcredit
IMPORTING
customer TYPE REF TO customer
RETURNING value(value) TYPE boolean
.

ENDCLASS. "credit DEFINITION


*----------------------------------------------------------------------*
* CLASS credit IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS credit IMPLEMENTATION.
METHOD hasgoodcredit.
DATA: mycustomer TYPE string.
mycustomer = customer->getname( ).
WRITE: / 'Check credit for ', mycustomer.
value = 'X'. "~true
ENDMETHOD. "hasgoodcredit

Version: 1.0
Side: 119
Project: Design Pattern

ENDCLASS. "credit IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS loan DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS loan DEFINITION.
PUBLIC SECTION.
METHODS:
hasnobadloans
IMPORTING
customer TYPE REF TO customer
RETURNING value(value) TYPE boolean.
ENDCLASS. "loan DEFINITION
*----------------------------------------------------------------------*
* CLASS loan IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS loan IMPLEMENTATION.
METHOD hasnobadloans.
DATA: mycustomer TYPE string.
mycustomer = customer->getname( ).
WRITE: / 'Check loans for ', mycustomer.
value = 'X'. "~true
ENDMETHOD. "hasnobadloans
ENDCLASS. "loan IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mortgage DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mortgage DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
,iseligible
IMPORTING
customer TYPE REF TO customer
amount TYPE i
RETURNING value(value) TYPE boolean
.

PRIVATE SECTION.
DATA: bank TYPE REF TO bank
,loan TYPE REF TO loan
,credit TYPE REF TO credit
.
ENDCLASS. "mortgage DEFINITION
*----------------------------------------------------------------------*
* CLASS mortgage IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mortgage IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT bank.
CREATE OBJECT loan.
CREATE OBJECT credit.
ENDMETHOD. "constructor
METHOD iseligible.
DATA: customername TYPE string.

customername = customer->getname( ).

Version: 1.0
Side: 120
Project: Design Pattern

WRITE: / customername, ' applies for ', amount, 'loan '.


value = 'X'. "~TRUE

IF bank->hassufficientsavings( customer = customer amount = amount ) NE 'X'.


value = '-'. " ~false
ELSEIF loan->hasnobadloans( customer ) NE 'X'.
value = '-'. "~false
ELSEIF credit->hasgoodcredit( customer ) NE 'X'.
value = '-'. "~false
ENDIF.

ENDMETHOD. "iseligible
ENDCLASS. "mortgage IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: mortgage TYPE REF TO mortgage
,customer TYPE REF TO customer
,eligible TYPE boolean
,customername TYPE string
.

CREATE OBJECT mortgage.


CREATE OBJECT customer EXPORTING name = 'Ann McKinsey'.
eligible = mortgage->iseligible( customer = customer amount = 125000 ).
customername = customer->getname( ).
WRITE: /,/ customername, ' Has been '.
IF eligible = 'X'.
WRITE: ' Approved '.
ELSE.
WRITE: ' Rejected '.
ENDIF.

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT
-------------
Ann McKinsey applies for 125.000 loan
Check bank for Ann McKinsey
Check loans for Ann McKinsey
Check credit for Ann McKinsey

Ann McKinsey Has been Approved

Version: 1.0
Side: 121
Project: Design Pattern

2.2.6 Flyweight (fluevægt)


A fine-grained instance used for efficient sharing

2.2.6.1 Definition
Use sharing to support large numbers of fine-grained (fin kornet) objects
efficiently.

2.2.6.2 UML class diagram

2.2.6.3 Participants
The classes and/or objects participating in this pattern are:
• Flyweight (Character)
o declares an interface through which flyweights can receive and act
on extrinsic state. (udefra kommende/ydre)
• ConcreteFlyweight (CharacterA, CharacterB, ..., CharacterZ)
o implements the Flyweight interface and adds storage for intrinsic
state, if any. A ConcreteFlyweight object must be sharable. Any
state it stores must be intrinsic, (indre/indefra kommende) that is,
it must be independent of the ConcreteFlyweight object's context.
• UnsharedConcreteFlyweight ( not used )
o not all Flyweight subclasses need to be shared. The Flyweight
interface enables sharing, but it doesn't enforce it. It is common
for UnsharedConcreteFlyweight objects to have ConcreteFlyweight
objects as children at some level in the flyweight object structure
(as the Row and Column classes have).
• FlyweightFactory (CharacterFactory)
o creates and manages flyweight objects ensures that flyweight are
shared properly. When a client requests a flyweight, the
FlyweightFactory objects supplies an existing instance or creates
one, if none exists.

Version: 1.0
Side: 122
Project: Design Pattern

• Client (FlyweightApp)
o maintains a reference to flyweight(s). computes or stores the
extrinsic state of flyweight(s).

2.2.6.4 Sample code In C#


This structural code demonstrates the Flyweight pattern in which a relatively
small number of objects is shared many times by different clients.

// Flyweight pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Flyweight.Structural
{
// MainApp test application

class MainApp
{
static void Main()
{
// Arbitrary extrinsic state
int extrinsicstate = 22;

FlyweightFactory f = new FlyweightFactory();

// Work with different flyweight instances


Flyweight fx = f.GetFlyweight("X");
fx.Operation(--extrinsicstate);

Flyweight fy = f.GetFlyweight("Y");
fy.Operation(--extrinsicstate);

Flyweight fz = f.GetFlyweight("Z");
fz.Operation(--extrinsicstate);

UnsharedConcreteFlyweight uf = new
UnsharedConcreteFlyweight();

uf.Operation(--extrinsicstate);

// Wait for user


Console.Read();
}
}

// "FlyweightFactory"

class FlyweightFactory
{
private Hashtable flyweights = new Hashtable();

// Constructor

Version: 1.0
Side: 123
Project: Design Pattern

public FlyweightFactory()
{
flyweights.Add("X", new ConcreteFlyweight());
flyweights.Add("Y", new ConcreteFlyweight());
flyweights.Add("Z", new ConcreteFlyweight());
}

public Flyweight GetFlyweight(string key)


{
return((Flyweight)flyweights[key]);
}
}

// "Flyweight"

abstract class Flyweight


{
public abstract void Operation(int extrinsicstate);
}

// "ConcreteFlyweight"

class ConcreteFlyweight : Flyweight


{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("ConcreteFlyweight: " + extrinsicstate);
}
}

// "UnsharedConcreteFlyweight"

class UnsharedConcreteFlyweight : Flyweight


{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("UnsharedConcreteFlyweight: " +
extrinsicstate);
}
}
}

Output
ConcreteFlyweight: 21
ConcreteFlyweight: 20
ConcreteFlyweight: 19
UnsharedConcreteFlyweight: 18

2.2.6.5 Sample code In ABAP


This structural code demonstrates the Flyweight pattern in which a relatively
small number of objects is shared many times by different clients.
*&---------------------------------------------------------------------*
*& Report ZDP_FLYWEIGHT_STRUCTURAL
*&

Version: 1.0
Side: 124
Project: Design Pattern

*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_flyweight_structural.

*----------------------------------------------------------------------*
* CLASS flyweight DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS flyweight DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
operation ABSTRACT IMPORTING extrincicstate TYPE i.
ENDCLASS. "flyweight DEFINITION

*----------------------------------------------------------------------*
* CLASS concreteflyweight DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteflyweight DEFINITION INHERITING FROM flyweight.
PUBLIC SECTION.
METHODS:
operation REDEFINITION.
ENDCLASS. "concreteflyweight DEFINITION

*----------------------------------------------------------------------*
* CLASS concreteflyweight IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteflyweight IMPLEMENTATION.
METHOD operation.
WRITE: /5(20)'ConcreteFlyweight', extrincicstate.
ENDMETHOD. "operation
ENDCLASS. "concreteflyweight IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS unsharedconcreteflyweight DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS unsharedconcreteflyweight DEFINITION INHERITING FROM flyweight.
PUBLIC SECTION.
METHODS:
operation REDEFINITION.
ENDCLASS. "unsharedconcreteflyweight DEFINITION
*----------------------------------------------------------------------*
* CLASS unsharedconcreteflyweight IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS unsharedconcreteflyweight IMPLEMENTATION.
METHOD operation.
WRITE: /5(20)'UnsharedConcreteFlyweight', extrincicstate.
ENDMETHOD. "operation
ENDCLASS. "unsharedconcreteflyweight IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS flyweightfactory DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*

Version: 1.0
Side: 125
Project: Design Pattern

CLASS flyweightfactory DEFINITION.


PUBLIC SECTION.
TYPES: BEGIN OF ty_flyweight
,key(1) TYPE c
,value TYPE REF TO concreteflyweight
,END OF ty_flyweight.
METHODS:
constructor
,getflyweight IMPORTING key TYPE c
RETURNING value(value) TYPE REF TO flyweight
.
PRIVATE SECTION.
DATA flyweights TYPE HASHED TABLE OF ty_flyweight
WITH UNIQUE KEY key.
ENDCLASS. "flyweightfactory DEFINITION

*----------------------------------------------------------------------*
* CLASS flyweightfactory IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS flyweightfactory IMPLEMENTATION.
METHOD constructor.
DATA: cf TYPE REF TO concreteflyweight
,buffer TYPE ty_flyweight .

CREATE OBJECT cf.


buffer-key = 'X'.
buffer-value = cf.
INSERT buffer INTO TABLE flyweights.

CREATE OBJECT cf.


buffer-key = 'Y'.
buffer-value = cf.
INSERT buffer INTO TABLE flyweights.

CREATE OBJECT cf.


buffer-key = 'Z'.
buffer-value = cf.
INSERT buffer INTO TABLE flyweights.
ENDMETHOD. "constructor
METHOD getflyweight.
DATA buffer TYPE ty_flyweight.
READ TABLE flyweights WITH TABLE KEY key = key INTO buffer.
value = buffer-value.
ENDMETHOD. "getflyweight
ENDCLASS. "flyweightfactory IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION

*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.

Version: 1.0
Side: 126
Project: Design Pattern

data: extrincicstate type i


,f type REF TO flyweightfactory
,fx TYPE REF TO flyweight
,fy TYPE REF TO flyweight
,fz TYPE REF TO flyweight
,uf TYPE REF TO unsharedconcreteflyweight
.

extrincicstate = 22.

CREATE OBJECT f.
fx = f->getflyweight( 'X' ).
subtract 1 from extrincicstate.
fx->operation( extrincicstate ).

subtract 1 from extrincicstate.


fy = f->getflyweight( 'Y' ).
fy->operation( extrincicstate ).

subtract 1 from extrincicstate.


fz = f->getflyweight( 'Z' ).
fz->operation( extrincicstate ).

subtract 1 from extrincicstate.


CREATE OBJECT uf.
uf->operation( extrincicstate ).

ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION

START-OF-SELECTION.
mainapp=>main( ).

OUTPUT:
-----------------

ConcreteFlyweight 21
ConcreteFlyweight 20
ConcreteFlyweight 19
UnsharedConcreteFlyw 18

2.2.6.6 Sample code In C#

This real-world code demonstrates the Flyweight pattern in which a relatively small number
of Character objects is shared many times by a document that has potentially many
characters.

// Flyweight pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Flyweight.RealWorld
{

// MainApp test application

Version: 1.0
Side: 127
Project: Design Pattern

class MainApp
{
static void Main()
{
// Build a document with text
string document = "AAZZBBZB";
char[] chars = document.ToCharArray();

CharacterFactory f = new CharacterFactory();

// extrinsic state
int pointSize = 10;

// For each character use a flyweight object


foreach (char c in chars)
{
pointSize++;
Character character = f.GetCharacter(c);
character.Display(pointSize);
}

// Wait for user


Console.Read();
}
}

// "FlyweightFactory"

class CharacterFactory
{
private Hashtable characters = new Hashtable();

public Character GetCharacter(char key)


{
// Uses "lazy initialization"
Character character = characters[key] as Character;
if (character == null)
{
switch (key)
{
case 'A': character = new CharacterA(); break;
case 'B': character = new CharacterB(); break;
//...
case 'Z': character = new CharacterZ(); break;
}
characters.Add(key, character);
}
return character;
}
}

// "Flyweight"

abstract class Character


{

Version: 1.0
Side: 128
Project: Design Pattern

protected char symbol;


protected int width;
protected int height;
protected int ascent;
protected int descent;
protected int pointSize;

public abstract void Display(int pointSize);


}

// "ConcreteFlyweight"

class CharacterA : Character


{
// Constructor
public CharacterA()
{
this.symbol = 'A';
this.height = 100;
this.width = 120;
this.ascent = 70;
this.descent = 0;
}

public override void Display(int pointSize)


{
this.pointSize = pointSize;
Console.WriteLine(this.symbol +
" (pointsize " + this.pointSize + ")");
}
}

// "ConcreteFlyweight"

class CharacterB : Character


{
// Constructor
public CharacterB()
{
this.symbol = 'B';
this.height = 100;
this.width = 140;
this.ascent = 72;
this.descent = 0;
}

public override void Display(int pointSize)


{
this.pointSize = pointSize;
Console.WriteLine(this.symbol +
" (pointsize " + this.pointSize + ")");
}

// ... C, D, E, etc.

Version: 1.0
Side: 129
Project: Design Pattern

// "ConcreteFlyweight"

class CharacterZ : Character


{
// Constructor
public CharacterZ()
{
this.symbol = 'Z';
this.height = 100;
this.width = 100;
this.ascent = 68;
this.descent = 0;
}

public override void Display(int pointSize)


{
this.pointSize = pointSize;
Console.WriteLine(this.symbol +
" (pointsize " + this.pointSize + ")");
}
}
}

Output
A (pointsize 11)
A (pointsize 12)
Z (pointsize 13)
Z (pointsize 14)
B (pointsize 15)
B (pointsize 16)
Z (pointsize 17)
B (pointsize 18)

2.2.7 Proxy
An object representing another object

2.2.7.1 Definition
Provide a surrogate or placeholder for another object to control access to it.

Version: 1.0
Side: 130
Project: Design Pattern

2.2.7.2 UML class diagram

2.2.7.3 Participants
The classes and/or objects participating in this pattern are:
• Proxy (MathProxy)
o maintains a reference that lets the proxy access the real subject.
Proxy may refer to a Subject if the RealSubject and Subject
interfaces are the same. provides an interface identical to Subject's
so that a proxy can be substituted for for the real subject. controls
access to the real subject and may be responsible for creating and
deleting it. other responsibilites depend on the kind of proxy:
ƒ remote proxies are responsible for encoding a request and its
arguments and for sending the encoded request to the real
subject in a different address space.
ƒ virtual proxies may cache additional information about the
real subject so that they can postpone accessing it. For
example, the ImageProxy from the Motivation caches the
real images's extent.
ƒ protection proxies check that the caller has the access
permissions required to perform a request.
• Subject (IMath)
o defines the common interface for RealSubject and Proxy so that a
Proxy can be used anywhere a RealSubject is expected.
• RealSubject (Math)
o defines the real object that the proxy represents.

2.2.7.4 Sample code In C#


This structural code demonstrates the Proxy pattern which provides a
representative object (proxy) that controls access to another similar object.
// Proxy pattern -- Structural example

Version: 1.0
Side: 131
Project: Design Pattern

using System;

namespace DoFactory.GangOfFour.Proxy.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
// Create proxy and request a service
Proxy proxy = new Proxy();
proxy.Request();

// Wait for user


Console.Read();
}
}

// "Subject"

abstract class Subject


{
public abstract void Request();
}

// "RealSubject"

class RealSubject : Subject


{
public override void Request()
{
Console.WriteLine("Called RealSubject.Request()");
}
}

// "Proxy"

class Proxy : Subject


{
RealSubject realSubject;

public override void Request()


{
// Use 'lazy initialization'
if (realSubject == null)
{
realSubject = new RealSubject();
}

realSubject.Request();
}
}
}

Version: 1.0
Side: 132
Project: Design Pattern

Output
Called RealSubject.Request()

2.2.7.5 Sample code In ABAP


*&---------------------------------------------------------------------*
*& Report ZDP_PROXY_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_proxy_structural.

*----------------------------------------------------------------------*
* CLASS subject DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subject DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
request ABSTRACT.
ENDCLASS. "subject DEFINITION

*----------------------------------------------------------------------*
* CLASS realsubject DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS realsubject DEFINITION INHERITING FROM subject.
PUBLIC SECTION.
METHODS:
request REDEFINITION.
ENDCLASS. "realsubject DEFINITION
*----------------------------------------------------------------------*
* CLASS realsubject IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS realsubject IMPLEMENTATION.
METHOD request.
WRITE: / 'Called RealSubject.Request()'.
ENDMETHOD. "request
ENDCLASS. "realsubject IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS proxy DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS proxy DEFINITION INHERITING FROM subject.
PUBLIC SECTION.
DATA: realsubject TYPE REF TO realsubject.
METHODS:

Version: 1.0
Side: 133
Project: Design Pattern

request REDEFINITION.
ENDCLASS. "proxy DEFINITION
*----------------------------------------------------------------------*
* CLASS proxy IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS proxy IMPLEMENTATION.
METHOD request.
* use lazy initialization
IF me->realsubject IS INITIAL.
CREATE OBJECT realsubject.
ENDIF.
me->realsubject->request( ).
ENDMETHOD. "request
ENDCLASS. "proxy 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().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA: proxy TYPE REF TO proxy.
CREATE OBJECT proxy.

Version: 1.0
Side: 134
Project: Design Pattern

proxy->request( ).

ENDMETHOD. "constructor

ENDCLASS. "lcl_application IMPLEMENTATION

START-OF-SELECTION.
lcl_application=>run( ).

Output:
Program ZDP_PROXY_STRUCTURAL

Called RealSubject.Request()

2.2.7.6 Sample code In C#


This real-world code demonstrates the Proxy pattern for a Math object represented by a
MathProxy object.

// Proxy pattern -- Real World example

using System;

namespace DoFactory.GangOfFour.Proxy.RealWorld
{

// Mainapp test application

class MainApp
{
static void Main()
{
// Create math proxy
MathProxy p = new MathProxy();

// Do the math
Console.WriteLine("4 + 2 = " + p.Add(4, 2));
Console.WriteLine("4 - 2 = " + p.Sub(4, 2));
Console.WriteLine("4 * 2 = " + p.Mul(4, 2));
Console.WriteLine("4 / 2 = " + p.Div(4, 2));

// Wait for user


Console.Read();
}
}

// "Subject"

public interface IMath


{
double Add(double x, double y);
double Sub(double x, double y);
double Mul(double x, double y);

Version: 1.0
Side: 135
Project: Design Pattern

double Div(double x, double y);


}

// "RealSubject"

class Math : IMath


{
public double Add(double x, double y){return x + y;}
public double Sub(double x, double y){return x - y;}
public double Mul(double x, double y){return x * y;}
public double Div(double x, double y){return x / y;}
}

// "Proxy Object"

class MathProxy : IMath


{
Math math;

public MathProxy()
{
math = new Math();
}

public double Add(double x, double y)


{
return math.Add(x,y);
}
public double Sub(double x, double y)
{
return math.Sub(x,y);
}
public double Mul(double x, double y)
{
return math.Mul(x,y);
}
public double Div(double x, double y)
{
return math.Div(x,y);
}
}
}

Output
4 + 2 = 6
4 - 2 = 2
4 * 2 = 8
4 / 2 = 2

2.2.7.7 Sample code In ABAP using interface


This real-world code demonstrates the Proxy pattern for a Math object represented by a
MathProxy object.
*&---------------------------------------------------------------------*
*& Report ZDP_PROXY_REALWORLD

Version: 1.0
Side: 136
Project: Design Pattern

*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_proxy_realworld.

*----------------------------------------------------------------------*
* INTERFACE if_math
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE if_math.
METHODS:
add IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
,sub IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
,mul IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
,div IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
.
ENDINTERFACE. "if_math

*----------------------------------------------------------------------*
* CLASS math DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS math DEFINITION.
PUBLIC SECTION.
INTERFACES:
if_math.
ALIASES:
add FOR if_math~add
,sub FOR if_math~sub
,mul FOR if_math~mul
,div FOR if_math~div.
ENDCLASS. "math DEFINITION
*----------------------------------------------------------------------*
* CLASS math IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS math IMPLEMENTATION.
METHOD add.
v = x + y.
ENDMETHOD. "add
METHOD sub.
v = x - y.
ENDMETHOD. "sub
METHOD mul.
v = x * y.
ENDMETHOD. "mul
METHOD div.
v = x DIV y.
ENDMETHOD. "div
ENDCLASS. "math IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS mathproxy DEFINITION

Version: 1.0
Side: 137
Project: Design Pattern

*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mathproxy DEFINITION.
PUBLIC SECTION.
DATA: math TYPE REF TO math.
INTERFACES:
if_math.
ALIASES:
add FOR if_math~add
,sub FOR if_math~sub
,mul FOR if_math~mul
,div FOR if_math~div.
METHODS:
constructor.
ENDCLASS. "mathproxy DEFINITION

*----------------------------------------------------------------------*
* CLASS mathproxy IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mathproxy IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT math.
ENDMETHOD. "constructor
METHOD add.
v = math->add( x = x y = y ).
ENDMETHOD. "add
METHOD sub.
v = math->sub( x = x y = y ).
ENDMETHOD. "sub
METHOD mul.
v = math->mul( x = x y = y ).
ENDMETHOD. "mul
METHOD div.
v = math->div( x = x y = y ).
ENDMETHOD. "div
ENDCLASS. "mathproxy 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().

Version: 1.0
Side: 138
Project: Design Pattern

*----------------------------------------------------------
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().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA: p TYPE REF TO mathproxy
,result TYPE i
.
CREATE OBJECT p.

* do the math
result = p->add( x = 4 y = 2 ).
WRITE:/ '4 + 2 = ', result.

result = p->sub( x = 4 y = 2 ).
WRITE:/ '4 - 2 = ', result.

result = p->mul( x = 4 y = 2 ).
WRITE:/ '4 * 2 = ', result.

result = p->div( x = 4 y = 2 ).
WRITE:/ '4 / 2 = ', result.
ENDMETHOD. "constructor

ENDCLASS. "lcl_application IMPLEMENTATION

START-OF-SELECTION.
lcl_application=>run( ).

2.3 Behavioral Patterns


2.3.1 Chain of Resp.
A way of passing a request between a chain of objects

2.3.1.1 Definition
Avoid coupling the sender of a request to its receiver by giving more than one
object a chance to handle the request. Chain the receiving objects and pass

Version: 1.0
Side: 139
Project: Design Pattern

the request along the chain until an object handles it. The client do know which
of the receiver that are the first I the chain.

2.3.1.2 UML class diagram

2.3.1.3 Participants
The classes and/or objects participating in this pattern are:
• Handler (Approver)
o defines an interface for handling the requests (optional)
implements the successor link
• ConcreteHandler (Director, VicePresident, President)
o handles requests it is responsible for can access its successor if the
ConcreteHandler can handle the request, it does so; otherwise it
forwards the request to its successor
• Client (ChainApp)
o initiates the request to a ConcreteHandler object on the chain

2.3.1.4 Sample code In C#


This structural code demonstrates the Chain of Responsibility pattern in which several
linked objects (the Chain) are offered the opportunity to respond to a request or hand it off
to the object next in line.

// Chain of Responsibility pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Chain.Structural
{
// MainApp test application

class MainApp
{
static void Main()
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();

Version: 1.0
Side: 140
Project: Design Pattern

h1.SetSuccessor(h2);
h2.SetSuccessor(h3);

// Generate and process request


int[] requests = {2, 5, 14, 22, 18, 3, 27, 20};

foreach (int request in requests)


{
h1.HandleRequest(request);
}

// Wait for user


Console.Read();
}
}

// "Handler"

abstract class Handler


{
protected Handler successor;

public void SetSuccessor(Handler successor)


{
this.successor = successor;
}

public abstract void HandleRequest(int request);


}

class ConcreteHandler1 : Handler


{
public override void HandleRequest(int request)
{
if (request >= 0 && request < 10)
{
Console.WriteLine("{0} handled request {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}

// "ConcreteHandler2"

class ConcreteHandler2 : Handler


{
public override void HandleRequest(int request)
{
if (request >= 10 && request < 20)
{

Version: 1.0
Side: 141
Project: Design Pattern

Console.WriteLine("{0} handled request {1}",


this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}

// "ConcreteHandler3"

class ConcreteHandler3 : Handler


{
public override void HandleRequest(int request)
{
if (request >= 20 && request < 30)
{
Console.WriteLine("{0} handled request {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
}

Output
ConcreteHandler1 handled request 2
ConcreteHandler1 handled request 5
ConcreteHandler2 handled request 14
ConcreteHandler3 handled request 22
ConcreteHandler2 handled request 18
ConcreteHandler1 handled request 3
ConcreteHandler3 handled request 27
ConcreteHandler3 handled request 20

2.3.1.5 Sample code In ABAP


This structural code demonstrates the Chain of Responsibility pattern in which several
linked objects (the Chain) are offered the opportunity to respond to a request or hand it off
to the object next in line.
*&---------------------------------------------------------------------*
*& Report ZDP_CHAINOFRESP_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_chainofresp_structural.
CLASS cl_abap_typedescr DEFINITION LOAD.

Version: 1.0
Side: 142
Project: Design Pattern

*----------------------------------------------------------------------*
* 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 handler DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS handler DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
setsuccessor IMPORTING successor TYPE REF TO handler
,handlerequest ABSTRACT IMPORTING request TYPE i
.
PROTECTED SECTION.
DATA:
successor TYPE REF TO handler.

ENDCLASS. "handler DEFINITION


*----------------------------------------------------------------------*
* CLASS handler IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS handler IMPLEMENTATION.
METHOD setsuccessor.
me->successor = successor.
ENDMETHOD. "setsuccessor
ENDCLASS. "handler IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS concretehandler1 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler1 DEFINITION INHERITING FROM handler.
PUBLIC SECTION.
METHODS:
handlerequest REDEFINITION.
ENDCLASS. "concretehandler1 DEFINITION
*----------------------------------------------------------------------*
* CLASS concretehandler1 IMPLEMENTATION

Version: 1.0
Side: 143
Project: Design Pattern

*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler1 IMPLEMENTATION.
METHOD handlerequest.
DATA: class_name TYPE abap_abstypename.
?get_class_name me class_name.

IF ( request >= 0 AND request < 10 ).


WRITE: / class_name, 'Handled request', request.
ELSEIF ( NOT successor IS INITIAL ).
me->successor->handlerequest( request ).
ENDIF.
ENDMETHOD. "handlerequest
ENDCLASS. "concretehandler1 IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS concretehandler2 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler2 DEFINITION INHERITING FROM handler.
PUBLIC SECTION.
METHODS:
handlerequest REDEFINITION.
ENDCLASS. "concretehandler2 DEFINITION
*----------------------------------------------------------------------*
* CLASS concretehandler2 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler2 IMPLEMENTATION.
METHOD handlerequest.
DATA: class_name TYPE abap_abstypename.
?get_class_name me class_name.

IF ( request >= 10 AND request < 20 ).


WRITE: / class_name, 'Handled request', request.
ELSEIF ( NOT successor IS INITIAL ).
me->successor->handlerequest( request ).
ENDIF.
ENDMETHOD. "handlerequest
ENDCLASS. "concretehandler2 IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS concretehandler3 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler3 DEFINITION INHERITING FROM handler.
PUBLIC SECTION.
METHODS:
handlerequest REDEFINITION.
ENDCLASS. "concretehandler3 DEFINITION
*----------------------------------------------------------------------*
* CLASS concretehandler3 IMPLEMENTATION
*----------------------------------------------------------------------*
*

Version: 1.0
Side: 144
Project: Design Pattern

*----------------------------------------------------------------------*
CLASS concretehandler3 IMPLEMENTATION.
METHOD handlerequest.
DATA: class_name TYPE abap_abstypename.
?get_class_name me class_name.

IF ( request >= 20 AND request < 30 ).


WRITE: / class_name, 'Handled request', request.
ELSEIF ( NOT successor IS INITIAL ).
me->successor->handlerequest( request ).
ENDIF.
ENDMETHOD. "handlerequest
ENDCLASS. "concretehandler3 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().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA:
h1 TYPE REF TO concretehandler1
,h2 TYPE REF TO concretehandler2
,h3 TYPE REF TO concretehandler3

Version: 1.0
Side: 145
Project: Design Pattern

,t_request TYPE TABLE OF i


,request TYPE i
.

* 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);

Version: 1.0
Side: 146
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)

Version: 1.0
Side: 147
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


{

Version: 1.0
Side: 148
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
*----------------------------------------------------------------------*

Version: 1.0
Side: 149
Project: Design Pattern

*
*----------------------------------------------------------------------*
CLASS purchase DEFINITION.
PUBLIC SECTION.
METHODS:
constructor IMPORTING number TYPE i
amount TYPE f
purpose TYPE string
,get_property IMPORTING name TYPE string
RETURNING value(dref) TYPE REF TO data.
PRIVATE SECTION.
DATA:
number TYPE i
,amount TYPE f
,purpose TYPE string
.

ENDCLASS. "purchase DEFINITION


*----------------------------------------------------------------------*
* CLASS purchase IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS purchase IMPLEMENTATION.
METHOD constructor.
me->number = number.
me->amount = amount.
me->purpose = purpose.
ENDMETHOD. "constructor

METHOD get_property.
CASE name.
WHEN 'NUMBER'.
GET REFERENCE OF me->number INTO dref.
WHEN 'AMOUNT'.
GET REFERENCE OF me->amount INTO dref.
WHEN 'PURPOSE'.
GET REFERENCE OF me->purpose INTO dref.
ENDCASE.
ENDMETHOD. "get_property

ENDCLASS. "purchase IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS approver DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
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
*----------------------------------------------------------------------*

Version: 1.0
Side: 150
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
*----------------------------------------------------------------------*

Version: 1.0
Side: 151
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

Version: 1.0
Side: 152
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().

Version: 1.0
Side: 153
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.

Version: 1.0
Side: 154
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
as objects allowing clients to execute or playback the requests.

// Command pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Command.Structural
{

// MainApp test applicatio

class MainApp
{
static void Main()

Version: 1.0
Side: 155
Project: Design Pattern

{
// Create receiver, command, and invoker
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();

// Set and execute command


invoker.SetCommand(command);
invoker.ExecuteCommand();

// Wait for user


Console.Read();
}
}

// "Command"

abstract class Command


{
protected Receiver receiver;

// Constructor
public Command(Receiver receiver)
{
this.receiver = receiver;
}

public abstract void Execute();


}

// "ConcreteCommand"

class ConcreteCommand : Command


{
// Constructor
public ConcreteCommand(Receiver receiver) :
base(receiver)
{
}

public override void Execute()


{
receiver.Action();
}
}

// "Receiver"

class Receiver
{
public void Action()
{
Console.WriteLine("Called Receiver.Action()");
}
}

Version: 1.0
Side: 156
Project: Design Pattern

// "Invoker"

class Invoker
{
private Command command;

public void SetCommand(Command command)


{
this.command = command;
}

public void ExecuteCommand()


{
command.Execute();
}
}
}

Output
Called Receiver.Action()

2.3.2.5 Sample code in ABAP


This structural code demonstrates the Command pattern which stores requests
as objects allowing clients to execute or playback the requests.
*&---------------------------------------------------------------------*
*& Report ZDP_COMMAND_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_command_structural.

*----------------------------------------------------------------------*
* CLASS receiver DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS receiver DEFINITION.
PUBLIC SECTION.
METHODS:
action.
ENDCLASS. "receiver DEFINITION
*----------------------------------------------------------------------*
* CLASS receiver IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS receiver IMPLEMENTATION.
METHOD action.
WRITE: / 'Console.WriteLine(Called Receiver.Action()'.
ENDMETHOD. "action

Version: 1.0
Side: 157
Project: Design Pattern

ENDCLASS. "receiver IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS command DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS command DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING receiver TYPE REF TO receiver
,execute ABSTRACT.
PROTECTED SECTION.
DATA: receiver TYPE REF TO receiver.
ENDCLASS. "command DEFINITION
*----------------------------------------------------------------------*
* CLASS command IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS command IMPLEMENTATION.
METHOD constructor.
me->receiver = receiver.
ENDMETHOD. "constructor
ENDCLASS. "command IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS concretecommand DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecommand DEFINITION INHERITING FROM command.
PUBLIC SECTION.
METHODS:
execute REDEFINITION.
ENDCLASS. "concretecommand DEFINITION
*----------------------------------------------------------------------*
* CLASS concretecommand IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecommand IMPLEMENTATION.
METHOD execute.
me->receiver->action( ).
ENDMETHOD. "execute
ENDCLASS. "concretecommand IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS invoker DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS invoker DEFINITION.
PUBLIC SECTION.
METHODS:
setcommand IMPORTING command TYPE REF TO command
,executecommand .

PRIVATE SECTION.

Version: 1.0
Side: 158
Project: Design Pattern

DATA: command TYPE REF TO command.


ENDCLASS. "invoker DEFINITION
*----------------------------------------------------------------------*
* CLASS invoker IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS invoker IMPLEMENTATION.
METHOD setcommand.
me->command = command.
ENDMETHOD. "setcommand
METHOD executecommand.
me->command->execute( ).
ENDMETHOD. "executecommand
ENDCLASS. "invoker 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().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA:
receiver TYPE REF TO receiver
,command TYPE REF TO concretecommand

Version: 1.0
Side: 159
Project: Design Pattern

,invoker TYPE REF TO invoker.

CREATE OBJECT receiver.


CREATE OBJECT command EXPORTING receiver = receiver .
CREATE OBJECT invoker.

* set and execute command


invoker->setcommand( command ).
invoker->executecommand( ).

ENDMETHOD. "constructor

ENDCLASS. "lcl_application IMPLEMENTATION

START-OF-SELECTION.
lcl_application=>run( ).

Output:
Program ZDP_COMMAND_STRUCTURAL

Console.WriteLine(Called Receiver.Action()

2.3.2.6 Sample code In C#


This real-world code demonstrates the Command pattern used in a simple
calculator with unlimited number of undo's and redo's. Note that in C# the
word 'operator' is a keyword. Prefixing it with '@' allows using it as an
identifier.
// Command pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Command.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Create user and let her compute
User user = new User();

user.Compute('+', 100);
user.Compute('-', 50);
user.Compute('*', 10);
user.Compute('/', 2);

// Undo 4 commands
user.Undo(4);

// Redo 3 commands
user.Redo(3);

Version: 1.0
Side: 160
Project: Design Pattern

// Wait for user


Console.Read();
}
}

// "Command"

abstract class Command


{
public abstract void Execute();
public abstract void UnExecute();
}

// "ConcreteCommand"

class CalculatorCommand : Command


{
char @operator;
int operand;
Calculator calculator;

// Constructor
public CalculatorCommand(Calculator calculator,
char @operator, int operand)
{
this.calculator = calculator;
this.@operator = @operator;
this.operand = operand;
}

public char Operator


{
set{ @operator = value; }
}

public int Operand


{
set{ operand = value; }
}

public override void Execute()


{
calculator.Operation(@operator, operand);
}

public override void UnExecute()


{
calculator.Operation(Undo(@operator), operand);
}

// Private helper function


private char Undo(char @operator)
{
char undo;
switch(@operator)

Version: 1.0
Side: 161
Project: Design Pattern

{
case '+': undo = '-'; break;
case '-': undo = '+'; break;
case '*': undo = '/'; break;
case '/': undo = '*'; break;
default : undo = ' '; break;
}
return undo;
}
}

// "Receiver"

class Calculator
{
private int curr = 0;

public void Operation(char @operator, int operand)


{
switch(@operator)
{
case '+': curr += operand; break;
case '-': curr -= operand; break;
case '*': curr *= operand; break;
case '/': curr /= operand; break;
}
Console.WriteLine(
"Current value = {0,3} (following {1} {2})",
curr, @operator, operand);
}
}

// "Invoker"

class User
{
// Initializers
private Calculator calculator = new Calculator();
private ArrayList commands = new ArrayList();

private int current = 0;

public void Redo(int levels)


{
Console.WriteLine("\n---- Redo {0} levels ", levels);
/ / Perform redo operations
for (int i = 0; i < levels; i++)
{
if (current < commands.Count - 1)
{
Command command = commands[current++] as Command;
command.Execute();
}
}
}

Version: 1.0
Side: 162
Project: Design Pattern

public void Undo(int levels)


{
Console.WriteLine("\n---- Undo {0} levels ", levels);
// Perform undo operations
for (int i = 0; i < levels; i++)
{
if (current > 0)
{
Command command = commands[--current] as Command;
command.UnExecute();
}
}
}

public void Compute(char @operator, int operand)


{
// Create command operation and execute it
Command command = new CalculatorCommand(
calculator, @operator, operand);
command.Execute();

// Add command to undo list


commands.Add(command);
current++;
}
}
}

Output
Current value = 100 (following + 100)
Current value = 50 (following - 50)
Current value = 500 (following * 10)
Current value = 250 (following / 2)

---- Undo 4 levels


Current value = 500 (following * 2)
Current value = 50 (following / 10)
Current value = 100 (following + 50)
Current value = 0 (following - 100)

---- Redo 3 levels


Current value = 100 (following + 100)
Current value = 50 (following - 50)
Current value = 500 (following * 10)

2.3.2.7 Sample code In C#


This real-world code demonstrates the Command pattern used in a simple
calculator with unlimited number of undo's and redo's. Note that in C# the
word 'operator' is a keyword. Prefixing it with '@' allows using it as an
identifier.
*&---------------------------------------------------------------------*
*& Report ZDP_COMMAND_REALWORLD
*&
*&---------------------------------------------------------------------*

Version: 1.0
Side: 163
Project: Design Pattern

*&
*&
*&---------------------------------------------------------------------*

REPORT zdp_command_realworld.

*----------------------------------------------------------------------*
* CLASS command DEFINITION
*----------------------------------------------------------------------*
* An abstract class does not have implementations for abstract methods
*----------------------------------------------------------------------*
CLASS command DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
execute ABSTRACT
,unexecute ABSTRACT .
ENDCLASS. "command DEFINITION

*----------------------------------------------------------------------*
* CLASS calculator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS calculator DEFINITION.
PUBLIC SECTION.
METHODS:
operation IMPORTING operator TYPE char1
operand TYPE i.
PRIVATE SECTION.
DATA: curr TYPE i VALUE 0.
ENDCLASS. "calculator DEFINITION

*----------------------------------------------------------------------*
* CLASS calculator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS calculator IMPLEMENTATION.
METHOD operation.
CASE operator.
WHEN '+'.
curr = curr + operand.
WHEN '-'.
curr = curr - operand.
WHEN '*'.
curr = curr * operand.
WHEN '/'.
curr = curr / operand.
ENDCASE.
WRITE: / 'Current Value = ', curr, '(following', (1) operator, (3) operand, ')'.
ENDMETHOD. "operation
ENDCLASS. "calculator IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS calculatorcommand DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*

Version: 1.0
Side: 164
Project: Design Pattern

CLASS calculatorcommand DEFINITION INHERITING FROM command.


PUBLIC SECTION.
DATA:
calculator TYPE REF TO calculator
,_operand TYPE REF TO zcl_integer
,_operator TYPE REF TO zcl_char
.
METHODS:
constructor IMPORTING calculator TYPE REF TO calculator
operator TYPE char1
operand TYPE i
,operator IMPORTING operator TYPE char1
,operand IMPORTING operand TYPE i
,execute REDEFINITION
,unexecute REDEFINITION
.
PRIVATE SECTION.
METHODS:
undo IMPORTING operator TYPE char1
RETURNING value(newoperator) TYPE char1.
ENDCLASS. "calculatorcommand DEFINITION

*----------------------------------------------------------------------*
* CLASS calculatorcommand IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS calculatorcommand IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
me->calculator = calculator.
CREATE OBJECT me->_operand.
me->_operand->set( operand ).
CREATE OBJECT me->_operator.
me->_operator->set( operator ).
ENDMETHOD. "constructor

METHOD operator.
me->_operator->set( operator ).
ENDMETHOD. "operator

METHOD operand.
me->_operand->set( operand ).
ENDMETHOD. "operand

METHOD execute.
DATA: l_operator TYPE char1
,l_operand TYPE integer.

l_operator = _operator->get( ).
l_operand = _operand->get( ).
me->calculator->operation( operator = l_operator
operand = l_operand ).
ENDMETHOD. "execute

METHOD unexecute.
DATA: l_operand TYPE integer
,l_operator TYPE char1 .
l_operand = _operand->get( ).

Version: 1.0
Side: 165
Project: Design Pattern

l_operator = _operator->get( ).
l_operator = me->undo( l_operator ).

me->calculator->operation( operator = l_operator


operand = l_operand ).
ENDMETHOD. "unexecute

METHOD undo.
CASE operator.
WHEN '+'. newoperator = '-'.
WHEN '-'. newoperator = '+'.
WHEN '*'. newoperator = '/'.
WHEN '/'. newoperator = '*'.
WHEN OTHERS. newoperator = ' '.
ENDCASE.
ENDMETHOD. "undo

ENDCLASS. "calculatorcommand IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS user DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS user DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
,redo IMPORTING levels TYPE integer
,undo IMPORTING levels TYPE integer
,compute IMPORTING operator TYPE char1
operand TYPE integer
.
PRIVATE SECTION.
DATA:
calculator TYPE REF TO calculator
,commands TYPE TABLE OF REF TO command
,current TYPE integer VALUE 0
,command TYPE REF TO calculatorcommand
.

ENDCLASS. "user DEFINITION

*----------------------------------------------------------------------*
* CLASS user IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS user IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT calculator.
ENDMETHOD. "constructor

METHOD redo.
DATA: i TYPE integer VALUE 1
,count TYPE i
,l_command TYPE REF TO command
,my_command TYPE REF TO calculatorcommand

Version: 1.0
Side: 166
Project: Design Pattern

.
DESCRIBE TABLE commands LINES count.
SUBTRACT 1 FROM count.
WRITE: /, / '----Redo levels ', levels.
* perform redo operations
WHILE i <= levels.
IF current <= count.
ADD 1 TO current.
READ TABLE commands INDEX current INTO l_command.
my_command ?= l_command.
l_command->execute( ).
ENDIF.
ADD 1 TO i.
ENDWHILE.
ENDMETHOD. "redo
"redo
METHOD undo.
DATA: i TYPE integer VALUE 0
,l_command TYPE REF TO command
,my_command TYPE REF TO calculatorcommand
.
WRITE: /,/ '----Undo levels ', levels.
* perform redo operations
WHILE i < levels.
IF current > 0.
READ TABLE commands INDEX current INTO l_command .
SUBTRACT 1 FROM current.
my_command ?= l_command.
l_command->unexecute( ).
ENDIF.
ADD 1 TO i.
ENDWHILE.
ENDMETHOD. "undo

METHOD compute.
* // Create command operation and execute it
CREATE OBJECT command EXPORTING calculator = calculator
operator = operator
operand = operand.
me->command->execute( ).
APPEND me->command TO commands.
ADD 1 TO current.
ENDMETHOD. "compute

ENDCLASS. "user 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
*----------------------------------------------------------

Version: 1.0
Side: 167
Project: Design Pattern

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

METHOD constructor.
DATA: user TYPE REF TO user.
super->constructor( ).
CREATE OBJECT user.

user->compute( operator ='+' operand = 100 ).


user->compute( operator ='-' operand = 50 ).
user->compute( operator ='*' operand = 10 ).
user->compute( operator ='/' operand = 2 ).
user->undo( 4 ).
user->redo( 3 ).

ENDMETHOD. "constructor
ENDCLASS. "lcl_application IMPLEMENTATION

START-OF-SELECTION.
lcl_application=>run( ).

Report ZDP_COMMAND_REALWORLD

Current Value = 100 (following + 100 )


Current Value = 50 (following - 50 )
Current Value = 500 (following * 10 )
Current Value = 250 (following / 2 )

Undo levels 4
Current Value = 500 (following * 2 )
Current Value = 50 (following / 10 )
Current Value = 100 (following + 50 )
Current Value = 0 (following - 100 )

Redo levels 3
Current Value = 100 (following + 100 )
Current Value = 50 (following - 50 )
Current Value = 500 (following * 10 )

Version: 1.0
Side: 168
Project: Design Pattern

2.3.3 Interpreter
A way to include language elements in a program

2.3.3.1 Definition
Given a language, define a representation for its grammar along with an interpreter that uses the
representation to interpret sentences in the language

2.3.3.2 UML class diagram

2.3.3.3 Participants
The classes and/or objects participating in this pattern are:

• AbstractExpression (Expression)
o declares an interface for executing an operation
• TerminalExpression ( ThousandExpression, HundredExpression, TenExpression,
OneExpression )
o implements an Interpret operation associated with terminal symbols in the grammar.
o an instance is required for every terminal symbol in the sentence.
• NonterminalExpression ( not used )
o one such class is required for every rule R ::= R1R2...Rn in the grammar
o maintains instance variables of type AbstractExpression for each of the symbols R1 through
Rn.
o implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically
calls itself recursively on the variables representing R1 through Rn.
• Context (Context)
o contains information that is global to the interpreter
• Client (InterpreterApp)
o builds (or is given) an abstract syntax tree representing a particular sentence in the
language that the grammar defines. The abstract syntax tree is assembled from instances of
the NonterminalExpression and TerminalExpression classes
o invokes the Interpret operation

Version: 1.0
Side: 169
Project: Design Pattern

2.3.3.4 Sample code I C#


This structural code demonstrates the Interpreter patterns, which using a defined
grammer, provides the interpreter that processes parsed statements.
// Interpreter pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Interpreter.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
Context context = new Context();

// Usually a tree
ArrayList list = new ArrayList();

// Populate 'abstract syntax tree'


list.Add(new TerminalExpression());
list.Add(new NonterminalExpression());
list.Add(new TerminalExpression());
list.Add(new TerminalExpression());

// Interpret
foreach (AbstractExpression exp in list)
{
exp.Interpret(context);
}

// Wait for user


Console.Read();
}
}

// "Context"

class Context
{
}

// "AbstractExpression"

abstract class AbstractExpression


{
public abstract void Interpret(Context context);
}

// "TerminalExpression"

class TerminalExpression : AbstractExpression

Version: 1.0
Side: 170
Project: Design Pattern

{
public override void Interpret(Context context)
{
Console.WriteLine("Called Terminal.Interpret()");
}
}

// "NonterminalExpression"

class NonterminalExpression : AbstractExpression


{
public override void Interpret(Context context)
{
Console.WriteLine("Called Nonterminal.Interpret()");
}
}
}

Output
Called Terminal.Interpret()
Called Nonterminal.Interpret()
Called Terminal.Interpret()
Called Terminal.Interpret()

This real-world code demonstrates the Interpreter pattern which is used to convert a Roman numeral to a
decimal.

// Interpreter pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Interpreter.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
string roman = "MCMXXVIII";
Context context = new Context(roman);

// Build the 'parse tree'


ArrayList tree = new ArrayList();
tree.Add(new ThousandExpression());
tree.Add(new HundredExpression());
tree.Add(new TenExpression());
tree.Add(new OneExpression());

// Interpret
foreach (Expression exp in tree)
{

Version: 1.0
Side: 171
Project: Design Pattern

exp.Interpret(context);
}

Console.WriteLine("{0} = {1}",
roman, context.Output);

// Wait for user


Console.Read();
}
}

// "Context"

class Context
{
private string input;
private int output;

// Constructor
public Context(string input)
{
this.input = input;
}

// Properties
public string Input
{
get{ return input; }
set{ input = value; }
}

public int Output


{
get{ return output; }
set{ output = value; }
}
}

// "AbstractExpression"

abstract class Expression


{
public void Interpret(Context context)
{
if (context.Input.Length == 0)
return;

if (context.Input.StartsWith(Nine()))
{
context.Output += (9 * Multiplier());
context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(Four()))
{
context.Output += (4 * Multiplier());
context.Input = context.Input.Substring(2);

Version: 1.0
Side: 172
Project: Design Pattern

}
else if (context.Input.StartsWith(Five()))
{
context.Output += (5 * Multiplier());
context.Input = context.Input.Substring(1);
}

while (context.Input.StartsWith(One()))
{
context.Output += (1 * Multiplier());
context.Input = context.Input.Substring(1);
}
}

public abstract string One();


public abstract string Four();
public abstract string Five();
public abstract string Nine();
public abstract int Multiplier();
}

// Thousand checks for the Roman Numeral M


// "TerminalExpression"

class ThousandExpression : Expression


{
public override string One() { return "M"; }
public override string Four(){ return " "; }
public override string Five(){ return " "; }
public override string Nine(){ return " "; }
public override int Multiplier() { return 1000; }
}

// Hundred checks C, CD, D or CM


// "TerminalExpression"

class HundredExpression : Expression


{
public override string One() { return "C"; }
public override string Four(){ return "CD"; }
public override string Five(){ return "D"; }
public override string Nine(){ return "CM"; }
public override int Multiplier() { return 100; }
}

// Ten checks for X, XL, L and XC


// "TerminalExpression"

class TenExpression : Expression


{
public override string One() { return "X"; }
public override string Four(){ return "XL"; }
public override string Five(){ return "L"; }
public override string Nine(){ return "XC"; }
public override int Multiplier() { return 10; }
}

Version: 1.0
Side: 173
Project: Design Pattern

// One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
// "TerminalExpression"

class OneExpression : Expression


{
public override string One() { return "I"; }
public override string Four(){ return "IV"; }
public override string Five(){ return "V"; }
public override string Nine(){ return "IX"; }
public override int Multiplier() { return 1; }
}
}

Output
MCMXXVIII = 1928

2.3.4 Iterator
Sequentially access the elements of a collection

2.3.4.1 Definition
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying
representation.

2.3.4.2 UML class diagram

2.3.4.3 Participants
The classes and/or objects participating in this pattern are:

• Iterator (AbstractIterator)
o defines an interface for accessing and traversing elements.
• ConcreteIterator (Iterator)

Version: 1.0
Side: 174
Project: Design Pattern

o implements the Iterator interface.


o keeps track of the current position in the traversal of the aggregate.
• Aggregate (AbstractCollection)
o defines an interface for creating an Iterator object
• ConcreteAggregate (Collection)
o implements the Iterator creation interface to return an instance of the proper
ConcreteIterator

2.3.4.4 Sample code I C#


This structural code demonstrates the Iterator pattern which provides for a way to traverse
(iterate) over a collection of items without detailing the underlying structure of the
collection.
// Iterator pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Iterator.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "Item A";
a[1] = "Item B";
a[2] = "Item C";
a[3] = "Item D";

// Create Iterator and provide aggregate


ConcreteIterator i = new ConcreteIterator(a);

Console.WriteLine("Iterating over collection:");

object item = i.First();


while (item != null)
{
Console.WriteLine(item);
item = i.Next();
}

// Wait for user


Console.Read();
}
}

// "Aggregate"

abstract class Aggregate

Version: 1.0
Side: 175
Project: Design Pattern

{
public abstract Iterator CreateIterator();
}

// "ConcreteAggregate"

class ConcreteAggregate : Aggregate


{
private ArrayList items = new ArrayList();

public override Iterator CreateIterator()


{
return new ConcreteIterator(this);
}

// Property
public int Count
{
get{ return items.Count; }
}

// Indexer
public object this[int index]
{
get{ return items[index]; }
set{ items.Insert(index, value); }
}
}

// "Iterator"

abstract class Iterator


{
public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}

// "ConcreteIterator"

class ConcreteIterator : Iterator


{
private ConcreteAggregate aggregate;
private int current = 0;

// Constructor
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}

public override object First()


{
return aggregate[0];
}

Version: 1.0
Side: 176
Project: Design Pattern

public override object Next()


{
object ret = null;
if (current < aggregate.Count - 1)
{
ret = aggregate[++current];
}

return ret;
}

public override object CurrentItem()


{
return aggregate[current];
}

public override bool IsDone()


{
return current >= aggregate.Count ? true : false ;
}
}
}

Output
Iterating over collection:
Item A
Item B
Item C
Item D

This real-world code demonstrates the Iterator pattern which is used to iterate over a
collection of items and skip a specific number of items each iteration.
// Iterator pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Iterator.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Build a collection
Collection collection = new Collection();
collection[0] = new Item("Item 0");
collection[1] = new Item("Item 1");
collection[2] = new Item("Item 2");
collection[3] = new Item("Item 3");
collection[4] = new Item("Item 4");

Version: 1.0
Side: 177
Project: Design Pattern

collection[5] = new Item("Item 5");


collection[6] = new Item("Item 6");
collection[7] = new Item("Item 7");
collection[8] = new Item("Item 8");

// Create iterator
Iterator iterator = new Iterator(collection);

// Skip every other item


iterator.Step = 2;

Console.WriteLine("Iterating over collection:");

for(Item item = iterator.First();


!iterator.IsDone; item = iterator.Next())
{
Console.WriteLine(item.Name);
}

// Wait for user


Console.Read();
}
}

class Item
{
string name;

// Constructor
public Item(string name)
{
this.name = name;
}

// Property
public string Name
{
get{ return name; }
}
}

// "Aggregate"

interface IAbstractCollection
{
Iterator CreateIterator();
}

// "ConcreteAggregate"

class Collection : IAbstractCollection


{
private ArrayList items = new ArrayList();

public Iterator CreateIterator()


{

Version: 1.0
Side: 178
Project: Design Pattern

return new Iterator(this);


}

// Property
public int Count
{
get{ return items.Count; }
}

// Indexer
public object this[int index]
{
get{ return items[index]; }
set{ items.Add(value); }
}
}

// "Iterator"

interface IAbstractIterator
{
Item First();
Item Next();
bool IsDone{ get; }
Item CurrentItem{ get; }
}

// "ConcreteIterator"

class Iterator : IAbstractIterator


{
private Collection collection;
private int current = 0;
private int step = 1;

// Constructor
public Iterator(Collection collection)
{
this.collection = collection;
}

public Item First()


{
current = 0;
return collection[current] as Item;
}

public Item Next()


{
current += step;
if (!IsDone)
return collection[current] as Item;
else
return null;
}

Version: 1.0
Side: 179
Project: Design Pattern

// Properties
public int Step
{
get{ return step; }
set{ step = value; }
}

public Item CurrentItem


{
get
{
return collection[current] as Item;
}
}

public bool IsDone


{
get
{
return current >= collection.Count ? true : false;
}
}
}
}

Output
Iterating over collection:
Item 0
Item 2
Item 4
Item 6
Item 8

2.3.5 Mediator
Defines simplified communication between classes

2.3.5.1 Definition
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by
keeping objects from referring to each other explicitly, and it lets you vary their interaction independently

Version: 1.0
Side: 180
Project: Design Pattern

2.3.5.2 UML class diagram

2.3.5.3 Participants
The classes and/or objects participating in this pattern are:

• Mediator (IChatroom)
o defines an interface for communicating with Colleague objects
• ConcreteMediator (Chatroom)
o implements cooperative behavior by coordinating Colleague objects
o knows and maintains its colleagues
• Colleague classes (Participant)
o each Colleague class knows its Mediator object
o each colleague communicates with its mediator whenever it would have otherwise
communicated with another colleague

2.3.5.4 Sample code I C#


This structural code demonstrates the Mediator pattern facilitating loosely coupled
communication between different objects and object types. The mediator is a central hub
through which all interaction must take place.
// Mediator pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Mediator.Structural
{

// Mainapp test application

class MainApp
{
static void Main()
{
ConcreteMediator m = new ConcreteMediator();

Version: 1.0
Side: 181
Project: Design Pattern

ConcreteColleague1 c1 = new ConcreteColleague1(m);


ConcreteColleague2 c2 = new ConcreteColleague2(m);

m.Colleague1 = c1;
m.Colleague2 = c2;

c1.Send("How are you?");


c2.Send("Fine, thanks");

// Wait for user


Console.Read();
}
}

// "Mediator"

abstract class Mediator


{
public abstract void Send(string message,
Colleague colleague);
}

// "ConcreteMediator"

class ConcreteMediator : Mediator


{
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;

public ConcreteColleague1 Colleague1


{
set{ colleague1 = value; }
}

public ConcreteColleague2 Colleague2


{
set{ colleague2 = value; }
}

public override void Send(string message,


Colleague colleague)
{
if (colleague == colleague1)
{
colleague2.Notify(message);
}
else
{
colleague1.Notify(message);
}
}
}

// "Colleague"

abstract class Colleague

Version: 1.0
Side: 182
Project: Design Pattern

{
protected Mediator mediator;

// Constructor
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
}

// "ConcreteColleague1"

class ConcreteColleague1 : Colleague


{
// Constructor
public ConcreteColleague1(Mediator mediator)
: base(mediator)
{
}

public void Send(string message)


{
mediator.Send(message, this);
}

public void Notify(string message)


{
Console.WriteLine("Colleague1 gets message: "
+ message);
}
}

// "ConcreteColleague2"

class ConcreteColleague2 : Colleague


{
// Constructor
public ConcreteColleague2(Mediator mediator)
: base(mediator)
{
}

public void Send(string message)


{
mediator.Send(message, this);
}

public void Notify(string message)


{
Console.WriteLine("Colleague2 gets message: "
+ message);
}
}
}

Output

Version: 1.0
Side: 183
Project: Design Pattern

Colleague2 gets message: How are you?

Colleague1 gets message: Fine, thanks

This real-world code demonstrates the Mediator pattern facilitating loosely coupled
communication between different Participants registering with a Chatroom. The Chatroom
is the central hub through which all communication takes place. At this point only one-to-
one communication is implemented in the Chatroom, but would be trivial to change to one-
to-many.

// Mediator pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Mediator.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Create chatroom
Chatroom chatroom = new Chatroom();

// Create participants and register them


Participant George = new Beatle("George");
Participant Paul = new Beatle("Paul");
Participant Ringo = new Beatle("Ringo");
Participant John = new Beatle("John") ;
Participant Yoko = new NonBeatle("Yoko");

chatroom.Register(George);
chatroom.Register(Paul);
chatroom.Register(Ringo);
chatroom.Register(John);
chatroom.Register(Yoko);

// Chatting participants
Yoko.Send ("John", "Hi John!");
Paul.Send ("Ringo", "All you need is love");
Ringo.Send("George", "My sweet Lord");
Paul.Send ("John", "Can't buy me love");
John.Send ("Yoko", "My sweet love") ;

// Wait for user


Console.Read();
}
}

// "Mediator"

abstract class AbstractChatroom

Version: 1.0
Side: 184
Project: Design Pattern

{
public abstract void Register(Participant participant);
public abstract void Send(
string from, string to, string message);
}

// "ConcreteMediator"

class Chatroom : AbstractChatroom


{
private Hashtable participants = new Hashtable();

public override void Register(Participant participant)


{
if (participants[participant.Name] == null)
{
participants[participant.Name] = participant;
}

participant.Chatroom = this;
}

public override void Send(


string from, string to, string message)
{
Participant pto = (Participant)participants[to];
if (pto != null)
{
pto.Receive(from, message);
}
}
}

// "AbstractColleague"

class Participant
{
private Chatroom chatroom;
private string name;

// Constructor
public Participant(string name)
{
this.name = name;
}

// Properties
public string Name
{
get{ return name; }
}

public Chatroom Chatroom


{
set{ chatroom = value; }
get{ return chatroom; }

Version: 1.0
Side: 185
Project: Design Pattern

public void Send(string to, string message)


{
chatroom.Send(name, to, message);
}

public virtual void Receive(


string from, string message)
{
Console.WriteLine("{0} to {1}: '{2}'",
from, Name, message);
}
}

//" ConcreteColleague1"

class Beatle : Participant


{
// Constructor
public Beatle(string name) : base(name)
{
}

public override void Receive(string from, string message)


{
Console.Write("To a Beatle: ");
base.Receive(from, message);
}
}

//" ConcreteColleague2"

class NonBeatle : Participant


{
// Constructor
public NonBeatle(string name) : base(name)
{
}

public override void Receive(string from, string message)


{
Console.Write("To a non-Beatle: ");
base.Receive(from, message);
}
}
}

Output
To a Beatle: Yoko to John: 'Hi John!'
To a Beatle: Paul to Ringo: 'All you need is love'
To a Beatle: Ringo to George: 'My sweet Lord'
To a Beatle: Paul to John: 'Can't buy me love'
To a non-Beatle: John to Yoko: 'My sweet love'

Version: 1.0
Side: 186
Project: Design Pattern

2.3.6 Memento
Capture and restore an object's internal state

2.3.6.1 Definition
Without violating encapsulation, capture and externalize an object's internal state so that the object can be
restored to this state later.

2.3.6.2 UML class diagram

2.3.6.3 Participants
The classes and/or objects participating in this pattern are:

• Memento (Memento)
o stores internal state of the Originator object. The memento may store as much or as little of
the originator's internal state as necessary at its originator's discretion.
o protect against access by objects of other than the originator. Mementos have effectively two
interfaces. Caretaker sees a narrow interface to the Memento -- it can only pass the
memento to the other objects. Originator, in contrast, sees a wide interface, one that lets it
access all the data necessary to restore itself to its previous state. Ideally, only the originator
that produces the memento would be permitted to access the memento's internal state.
• Originator (SalesProspect)
o creates a memento containing a snapshot of its current internal state.
o uses the memento to restore its internal state
• Caretaker (Caretaker)
o is responsible for the memento's safekeeping
o never operates on or examines the contents of a memento.

2.3.6.4 Sample code I C#


This structural code demonstrates the Memento pattern which temporary saves and
restores another object's internal state.

// Memento pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Memento.Structural
{

Version: 1.0
Side: 187
Project: Design Pattern

// MainApp test application

class MainApp
{
static void Main()
{
Originator o = new Originator();
o.State = "On";

// Store internal state


Caretaker c = new Caretaker();
c.Memento = o.CreateMemento();

// Continue changing originator


o.State = "Off";

// Restore saved state


o.SetMemento(c.Memento);

// Wait for user


Console.Read();
}
}

// "Originator"

class Originator
{
private string state;

// Property
public string State
{
get{ return state; }
set
{
state = value;
Console.WriteLine("State = " + state);
}
}

public Memento CreateMemento()


{
return (new Memento(state));
}

public void SetMemento(Memento memento)


{
Console.WriteLine("Restoring state:");
State = memento.State;
}
}

// "Memento"

Version: 1.0
Side: 188
Project: Design Pattern

class Memento
{
private string state;

// Constructor
public Memento(string state)
{
this.state = state;
}

// Property
public string State
{
get{ return state; }
}
}

// "Caretaker"

class Caretaker
{
private Memento memento;

// Property
public Memento Memento
{
set{ memento = value; }
get{ return memento; }
}
}
}

Output
State = On
State = Off
Restoring state:
State = On

This real-world code demonstrates the Memento pattern which temporarily saves and then
restores the SalesProspect's internal state.
// Memento pattern -- Real World example

using System;

namespace DoFactory.GangOfFour.Memento.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
SalesProspect s = new SalesProspect();

Version: 1.0
Side: 189
Project: Design Pattern

s.Name = "Noel van Halen";


s.Phone = "(412) 256-0990";
s.Budget = 25000.0;

// Store internal state


ProspectMemory m = new ProspectMemory();
m.Memento = s.SaveMemento();

// Continue changing originator


s.Name = "Leo Welch";
s.Phone = "(310) 209-7111";
s.Budget = 1000000.0;

// Restore saved state


s.RestoreMemento(m.Memento);

// Wait for user


Console.Read();
}
}

// "Originator"

class SalesProspect
{
private string name;
private string phone;
private double budget;

// Properties
public string Name
{
get{ return name; }
set
{
name = value;
Console.WriteLine("Name: " + name);
}
}

public string Phone


{
get{ return phone; }
set
{
phone = value;
Console.WriteLine("Phone: " + phone);
}
}

public double Budget


{
get{ return budget; }
set
{
budget = value;

Version: 1.0
Side: 190
Project: Design Pattern

Console.WriteLine("Budget: " + budget);


}
}

public Memento SaveMemento()


{
Console.WriteLine("\nSaving state --\n");
return new Memento(name, phone, budget);
}

public void RestoreMemento(Memento memento)


{
Console.WriteLine("\nRestoring state --\n");
this.Name = memento.Name;
this.Phone = memento.Phone;
this.Budget = memento.Budget;
}
}

// "Memento"

class Memento
{
private string name;
private string phone;
private double budget;

// Constructor
public Memento(string name, string phone, double budget)
{
this.name = name;
this.phone = phone;
this.budget = budget;
}

// Properties
public string Name
{
get{ return name; }
set{ name = value; }
}

public string Phone


{
get{ return phone; }
set{ phone = value; }
}

public double Budget


{
get{ return budget; }
set{ budget = value; }
}
}

// "Caretaker"

Version: 1.0
Side: 191
Project: Design Pattern

class ProspectMemory
{
private Memento memento;

// Property
public Memento Memento
{
set{ memento = value; }
get{ return memento; }
}
}
}

Output
Name: Noel van Halen
Phone: (412) 256-0990
Budget: 25000

Saving state --

Name: Leo Welch


Phone: (310) 209-7111
Budget: 1000000

Restoring state --

Name: Noel van Halen


Phone: (412) 256-0990
Budget: 25000

2.3.7 Observer
A way of notifying change to a number of classes

2.3.7.1 Definition
Define a one-to-many dependency between objects so that when one object changes state, all its
dependents are notified and updated automatically.

Version: 1.0
Side: 192
Project: Design Pattern

2.3.7.2 UML class diagram

2.3.7.3 Participants
The classes and/or objects participating in this pattern are:

• Subject (Stock)
o knows its observers. Any number of Observer objects may observe a subject
o provides an interface for attaching and detaching Observer objects.
• ConcreteSubject (IBM)
o stores state of interest to ConcreteObserver
o sends a notification to its observers when its state changes
• Observer (IInvestor)
o defines an updating interface for objects that should be notified of changes in a subject.
• ConcreteObserver (Investor)
o maintains a reference to a ConcreteSubject object
o stores state that should stay consistent with the subject's
o implements the Observer updating interface to keep its state consistent with the subject's

2.3.7.4 Sample code I C#


This structural code demonstrates the Observer pattern in which registered objects are
notified of and updated with a state change.

// Observer pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Observer.Structural
{

Version: 1.0
Side: 193
Project: Design Pattern

// MainApp test application

class MainApp
{
static void Main()
{
// Configure Observer pattern
ConcreteSubject s = new ConcreteSubject();

s.Attach(new ConcreteObserver(s,"X"));
s.Attach(new ConcreteObserver(s,"Y"));
s.Attach(new ConcreteObserver(s,"Z"));

// Change subject and notify observers


s.SubjectState = "ABC";
s.Notify();

// Wait for user


Console.Read();
}
}

// "Subject"

abstract class Subject


{
private ArrayList observers = new ArrayList();

public void Attach(Observer observer)


{
observers.Add(observer);
}

public void Detach(Observer observer)


{
observers.Remove(observer);
}

public void Notify()


{
foreach (Observer o in observers)
{
o.Update();
}
}
}

// "ConcreteSubject"

class ConcreteSubject : Subject


{
private string subjectState;

// Property
public string SubjectState

Version: 1.0
Side: 194
Project: Design Pattern

{
get{ return subjectState; }
set{ subjectState = value; }
}
}

// "Observer"

abstract class Observer


{
public abstract void Update();
}

// "ConcreteObserver"

class ConcreteObserver : Observer


{
private string name;
private string observerState;
private ConcreteSubject subject;

// Constructor
public ConcreteObserver(
ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}

public override void Update()


{
observerState = subject.SubjectState;
Console.WriteLine("Observer {0}'s new state is {1}",
name, observerState);
}

// Property
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
}
}

Output
Observer X's new state is ABC
Observer Y's new state is ABC
Observer Z's new state is ABC

This real-world code demonstrates the Observer pattern in which registered investors are
notified every time a stock changes value.

// Observer pattern -- Real World example

Version: 1.0
Side: 195
Project: Design Pattern

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Observer.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Create investors
Investor s = new Investor("Sorros");
Investor b = new Investor("Berkshire");

// Create IBM stock and attach investors


IBM ibm = new IBM("IBM", 120.00);
ibm.Attach(s);
ibm.Attach(b);

// Change price, which notifies investors


ibm.Price = 120.10;
ibm.Price = 121.00;
ibm.Price = 120.50;
ibm.Price = 120.75;

// Wait for user


Console.Read();
}
}

// "Subject"

abstract class Stock


{
protected string symbol;
protected double price;
private ArrayList investors = new ArrayList();

// Constructor
public Stock(string symbol, double price)
{
this.symbol = symbol;
this.price = price;
}

public void Attach(Investor investor)


{
investors.Add(investor);
}

public void Detach(Investor investor)


{
investors.Remove(investor);
}

Version: 1.0
Side: 196
Project: Design Pattern

public void Notify()


{
foreach (Investor investor in investors)
{
investor.Update(this);
}
Console.WriteLine("");
}

// Properties
public double Price
{
get{ return price; }
set
{
price = value;
Notify();
}
}

public string Symbol


{
get{ return symbol; }
set{ symbol = value; }
}
}

// "ConcreteSubject"

class IBM : Stock


{
// Constructor
public IBM(string symbol, double price)
: base(symbol, price)
{
}
}

// "Observer"

interface IInvestor
{
void Update(Stock stock);
}

// "ConcreteObserver"

class Investor : IInvestor


{
private string name;
private Stock stock;

// Constructor
public Investor(string name)
{

Version: 1.0
Side: 197
Project: Design Pattern

this.name = name;
}

public void Update(Stock stock)


{
Console.WriteLine("Notified {0} of {1}'s " +
"change to {2:C}", name, stock.Symbol, stock.Price);
}

// Property
public Stock Stock
{
get{ return stock; }
set{ stock = value; }
}
}
}

Output
Notified Sorros of IBM's change to $120.10
Notified Berkshire of IBM's change to $120.10

Notified Sorros of IBM's change to $121.00


Notified Berkshire of IBM's change to $121.00

Notified Sorros of IBM's change to $120.50


Notified Berkshire of IBM's change to $120.50

Notified Sorros of IBM's change to $120.75


Notified Berkshire of IBM's change to $120.75

2.3.8 State
Alter an object's behavior when its state changes

2.3.8.1 Definition
Allow an object to alter its behavior when its internal state changes. The object will appear to change its
class

2.3.8.2 UML class diagram

Version: 1.0
Side: 198
Project: Design Pattern

2.3.8.3 Participants
The classes and/or objects participating in this pattern are:

• Context (Account)
o defines the interface of interest to clients
o maintains an instance of a ConcreteState subclass that defines the current state.
• State (State)
o defines an interface for encapsulating the behavior associated with a particular state of the
Context.
• Concrete State (RedState, SilverState, GoldState)
o each subclass implements a behavior associated with a state of Context

2.3.8.4 Sample code I C#

This structural code demonstrates the State pattern which allows an object to behave
differently depending on its internal state. The difference in behavior is delegated to
objects that represent this state.

// State pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.State.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
// Setup context in a state
Context c = new Context(new ConcreteStateA());

// Issue requests, which toggles state


c.Request();
c.Request();
c.Request();
c.Request();

// Wait for user


Console.Read();
}
}

// "State"

abstract class State


{
public abstract void Handle(Context context);

Version: 1.0
Side: 199
Project: Design Pattern

// "ConcreteStateA"

class ConcreteStateA : State


{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}

// "ConcreteStateB"

class ConcreteStateB : State


{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}

// "Context"

class Context
{
private State state;

// Constructor
public Context(State state)
{
this.State = state;
}

// Property
public State State
{
get{ return state; }
set
{
state = value;
Console.WriteLine("State: " +
state.GetType().Name);
}
}

public void Request()


{
state.Handle(this);
}
}
}

Output
State: ConcreteStateA
State: ConcreteStateB
State: ConcreteStateA

Version: 1.0
Side: 200
Project: Design Pattern

State: ConcreteStateB
State: ConcreteStateA

This real-world code demonstrates the State pattern which allows an Account to behave
differently depending on its balance. The difference in behavior is delegated to State
objects called RedState, SilverState and GoldState. These states represent overdrawn
accounts, starter accounts, and accounts in good standing.

// State pattern -- Real World example

using System;

namespace DoFactory.GangOfFour.State.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Open a new account
Account account = new Account("Jim Johnson");

// Apply financial transactions


account.Deposit(500.0);
account.Deposit(300.0);
account.Deposit(550.0);
account.PayInterest();
account.Withdraw(2000.00);
account.Withdraw(1100.00);

// Wait for user


Console.Read();
}
}

// "State"

abstract class State


{
protected Account account;
protected double balance;

protected double interest;


protected double lowerLimit;
protected double upperLimit;

// Properties
public Account Account
{
get{ return account; }
set{ account = value; }
}

Version: 1.0
Side: 201
Project: Design Pattern

public double Balance


{
get{ return balance; }
set{ balance = value; }
}

public abstract void Deposit(double amount);


public abstract void Withdraw(double amount);
public abstract void PayInterest();
}

// "ConcreteState"

// Account is overdrawn

class RedState : State


{
double serviceFee;

// Constructor
public RedState(State state)
{
this.balance = state.Balance;
this.account = state.Account;
Initialize();
}

private void Initialize()


{
// Should come from a datasource
interest = 0.0;
lowerLimit = -100.0;
upperLimit = 0.0;
serviceFee = 15.00;
}

public override void Deposit(double amount)


{
balance += amount;
StateChangeCheck();
}

public override void Withdraw(double amount)


{
amount = amount - serviceFee;
Console.WriteLine("No funds available for withdrawal!");
}

public override void PayInterest()


{
// No interest is paid
}

private void StateChangeCheck()


{
if (balance > upperLimit)

Version: 1.0
Side: 202
Project: Design Pattern

{
account.State = new SilverState(this);
}
}
}

// "ConcreteState"

// Silver is non-interest bearing state

class SilverState : State


{
// Overloaded constructors

public SilverState(State state) :


this( state.Balance, state.Account)
{
}

public SilverState(double balance, Account account)


{
this.balance = balance;
this.account = account;
Initialize();
}

private void Initialize()


{
// Should come from a datasource
interest = 0.0;
lowerLimit = 0.0;
upperLimit = 1000.0;
}

public override void Deposit(double amount)


{
balance += amount;
StateChangeCheck();
}

public override void Withdraw(double amount)


{
balance -= amount;
StateChangeCheck();
}

public override void PayInterest()


{
balance += interest * balance;
StateChangeCheck();
}

private void StateChangeCheck()


{
if (balance < lowerLimit)
{

Version: 1.0
Side: 203
Project: Design Pattern

account.State = new RedState(this);


}
else if (balance > upperLimit)
{
account.State = new GoldState(this);
}
}
}

// "ConcreteState"

// Interest bearing state

class GoldState : State


{
// Overloaded constructors
public GoldState(State state)
: this(state.Balance,state.Account)
{
}

public GoldState(double balance, Account account)


{
this.balance = balance;
this.account = account;
Initialize();
}

private void Initialize()


{
// Should come from a database
interest = 0.05;
lowerLimit = 1000.0;
upperLimit = 10000000.0;
}

public override void Deposit(double amount)


{
balance += amount;
StateChangeCheck();
}

public override void Withdraw(double amount)


{
balance -= amount;
StateChangeCheck();
}

public override void PayInterest()


{
balance += interest * balance;
StateChangeCheck();
}

private void StateChangeCheck()


{

Version: 1.0
Side: 204
Project: Design Pattern

if (balance < 0.0)


{
account.State = new RedState(this);
}
else if (balance < lowerLimit)
{
account.State = new SilverState(this);
}
}
}

// "Context"

class Account
{
private State state;
private string owner;

// Constructor
public Account(string owner)
{
// New accounts are 'Silver' by default
this.owner = owner;
state = new SilverState(0.0, this);
}

// Properties
public double Balance
{
get{ return state.Balance; }
}

public State State


{
get{ return state; }
set{ state = value; }
}

public void Deposit(double amount)


{
state.Deposit(amount);
Console.WriteLine("Deposited {0:C} --- ", amount);
Console.WriteLine(" Balance = {0:C}", this.Balance);
Console.WriteLine(" Status = {0}\n" ,
this.State.GetType().Name);
Console.WriteLine("");
}

public void Withdraw(double amount)


{
state.Withdraw(amount);
Console.WriteLine("Withdrew {0:C} --- ", amount);
Console.WriteLine(" Balance = {0:C}", this.Balance);
Console.WriteLine(" Status = {0}\n" ,
this.State.GetType().Name);
}

Version: 1.0
Side: 205
Project: Design Pattern

public void PayInterest()


{
state.PayInterest();
Console.WriteLine("Interest Paid --- ");
Console.WriteLine(" Balance = {0:C}", this.Balance);
Console.WriteLine(" Status = {0}\n" ,
this.State.GetType().Name);
}
}
}

Output
Deposited $500.00 ---
Balance = $500.00
Status = SilverState

Deposited $300.00 ---


Balance = $800.00
Status = SilverState

Deposited $550.00 ---


Balance = $1,350.00
Status = GoldState

Interest Paid ---


Balance = $1,417.50
Status = GoldState

Withdrew $2,000.00 ---


Balance = ($582.50)
Status = RedState

No funds available for withdrawal!


Withdrew $1,100.00 ---
Balance = ($582.50)
Status = RedState

2.3.9 Strategy
Encapsulates an algorithm inside a class

2.3.9.1 Definition
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the
algorithm vary independently from clients that use it

Version: 1.0
Side: 206
Project: Design Pattern

2.3.9.2 UML class diagram

2.3.9.3 Participants
The classes and/or objects participating in this pattern are:

• Strategy (SortStrategy)
o declares an interface common to all supported algorithms. Context uses this interface to call
the algorithm defined by a ConcreteStrategy
• ConcreteStrategy (QuickSort, ShellSort, MergeSort)
o implements the algorithm using the Strategy interface
• Context (SortedList)
o is configured with a ConcreteStrategy object
o maintains a reference to a Strategy object
o may define an interface that lets Strategy access its data.

2.3.9.4 Sample code In C#


This structural code demonstrates the Strategy pattern which encapsulates functionality in
the form of an object. This allows clients to dynamically change algorithmic strategies.

// Strategy pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Strategy.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
Context context;

// Three contexts following different strategies


context = new Context(new ConcreteStrategyA());
context.ContextInterface();

Version: 1.0
Side: 207
Project: Design Pattern

context = new Context(new ConcreteStrategyB());


context.ContextInterface();

context = new Context(new ConcreteStrategyC());


context.ContextInterface();

// Wait for user


Console.Read();
}
}

// "Strategy"

abstract class Strategy


{
public abstract void AlgorithmInterface();
}

// "ConcreteStrategyA"

class ConcreteStrategyA : Strategy


{
public override void AlgorithmInterface()
{
Console.WriteLine(
"Called ConcreteStrategyA.AlgorithmInterface()");
}
}

// "ConcreteStrategyB"

class ConcreteStrategyB : Strategy


{
public override void AlgorithmInterface()
{
Console.WriteLine(
"Called ConcreteStrategyB.AlgorithmInterface()");
}
}

// "ConcreteStrategyC"

class ConcreteStrategyC : Strategy


{
public override void AlgorithmInterface()
{
Console.WriteLine(
"Called ConcreteStrategyC.AlgorithmInterface()");
}
}

// "Context"

class Context
{
Strategy strategy;

Version: 1.0
Side: 208
Project: Design Pattern

// Constructor
public Context(Strategy strategy)
{
this.strategy = strategy;
}

public void ContextInterface()


{
strategy.AlgorithmInterface();
}
}
}

Output
Called ConcreteStrategyA.AlgorithmInterface()
Called ConcreteStrategyB.AlgorithmInterface()
Called ConcreteStrategyC.AlgorithmInterface()

This real-world code demonstrates the Strategy pattern which encapsulates sorting
algorithms in the form of sorting objects. This allows clients to dynamically change sorting
strategies including Quicksort, Shellsort, and Mergesort.
// Strategy pattern -- Real World example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Strategy.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
// Two contexts following different strategies
SortedList studentRecords = new SortedList();

studentRecords.Add("Samual");
studentRecords.Add("Jimmy");
studentRecords.Add("Sandra");
studentRecords.Add("Vivek");
studentRecords.Add("Anna");

studentRecords.SetSortStrategy(new QuickSort());
studentRecords.Sort();

studentRecords.SetSortStrategy(new ShellSort());
studentRecords.Sort();

studentRecords.SetSortStrategy(new MergeSort());
studentRecords.Sort();

Version: 1.0
Side: 209
Project: Design Pattern

// Wait for user


Console.Read();
}
}

// "Strategy"

abstract class SortStrategy


{
public abstract void Sort(ArrayList list);
}

// "ConcreteStrategy"

class QuickSort : SortStrategy


{
public override void Sort(ArrayList list)
{
list.Sort(); // Default is Quicksort
Console.WriteLine("QuickSorted list ");
}
}

// "ConcreteStrategy"

class ShellSort : SortStrategy


{
public override void Sort(ArrayList list)
{
//list.ShellSort(); not-implemented
Console.WriteLine("ShellSorted list ");
}
}

// "ConcreteStrategy"

class MergeSort : SortStrategy


{
public override void Sort(ArrayList list)
{
//list.MergeSort(); not-implemented
Console.WriteLine("MergeSorted list ");
}
}

// "Context"

class SortedList
{
private ArrayList list = new ArrayList();
private SortStrategy sortstrategy;

public void SetSortStrategy(SortStrategy sortstrategy)


{
this.sortstrategy = sortstrategy;
}

Version: 1.0
Side: 210
Project: Design Pattern

public void Add(string name)


{
list.Add(name);
}

public void Sort()


{
sortstrategy.Sort(list);

// Display results
foreach (string name in list)
{
Console.WriteLine(" " + name);
}
Console.WriteLine();
}
}
}

Output
QuickSorted list
Anna
Jimmy
Samual
Sandra
Vivek

ShellSorted list
Anna
Jimmy
Samual
Sandra
Vivek

MergeSorted list
Anna
Jimmy
Samual
Sandra
Vivek

2.3.10 Template Method


Defer the exact steps of an algorithm to a subclass

2.3.10.1 Definition
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method
lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure

Version: 1.0
Side: 211
Project: Design Pattern

2.3.10.2 UML class diagram

2.3.10.3 Participants
The classes and/or objects participating in this pattern are:

• AbstractClass (DataObject)
o defines abstract primitive operations that concrete subclasses define to implement steps of
an algorithm
o implements a template method defining the skeleton of an algorithm. The template method
calls primitive operations as well as operations defined in AbstractClass or those of other
objects.
• ConcreteClass (CustomerDataObject)
o implements the primitive operations ot carry out subclass-specific steps of the algorithm

2.3.10.4 Sample code In C#


This structural code demonstrates the Template method which provides a skeleton calling sequence of
methods. One or more steps can be deferred to subclasses which implement these steps without changing
the overall calling sequence.
// Template pattern -- Structural example

using System;

namespace DoFactory.GangOfFour.Template.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
AbstractClass c;

Version: 1.0
Side: 212
Project: Design Pattern

c = new ConcreteClassA();
c.TemplateMethod();

c = new ConcreteClassB();
c.TemplateMethod();

// Wait for user


Console.Read();
}
}

// "AbstractClass"

abstract class AbstractClass


{
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();

// The "Template method"


public void TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
Console.WriteLine("");
}
}

// "ConcreteClass"

class ConcreteClassA : AbstractClass


{
public override void PrimitiveOperation1()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation1()");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation2()");
}
}

class ConcreteClassB : AbstractClass


{
public override void PrimitiveOperation1()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation1()");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation2()");
}
}
}

Output

Version: 1.0
Side: 213
Project: Design Pattern

ConcreteClassA.PrimitiveOperation1()
ConcreteClassA.PrimitiveOperation2()

This real-world code demonstrates a Template method named Run() which provides a
skeleton calling sequence of methods. Implementation of these steps are deferred to the
CustomerDataObject subclass which implements the Connect, Select, Process, and
Disconnect methods.
// Template pattern -- Real World example

using System;
using System.Data;
using System.Data.OleDb;

namespace DoFactory.GangOfFour.Template.RealWorld
{

// MainApp test application

class MainApp
{
static void Main()
{
DataAccessObject dao;

dao = new Categories();


dao.Run();

dao = new Products();


dao.Run();

// Wait for user


Console.Read();
}
}

// "AbstractClass"

abstract class DataAccessObject


{
protected string connectionString;

protected DataSet dataSet;

public virtual void Connect()


{
// Make sure mdb is on c:\
connectionString =
"provider=Microsoft.JET.OLEDB.4.0; " +
"data source=c:\\nwind.mdb";
}

public abstract void Select();


public abstract void Process();

public virtual void Disconnect()

Version: 1.0
Side: 214
Project: Design Pattern

{
connectionString = "";
}

// The "Template Method"

public void Run()


{
Connect();
Select();
Process();
Disconnect();
}
}

// "ConcreteClass"

class Categories : DataAccessObject


{
public override void Select()
{
string sql = "select CategoryName from Categories";
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(
sql, connectionString);

dataSet = new DataSet();


dataAdapter.Fill(dataSet, "Categories");
}

public override void Process()


{
Console.WriteLine("Categories ---- ");

DataTable dataTable = dataSet.Tables["Categories"];


foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["CategoryName"]);
}
Console.WriteLine();
}
}

class Products : DataAccessObject


{
public override void Select()
{
string sql = "select ProductName from Products";
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(
sql, connectionString);

dataSet = new DataSet();


dataAdapter.Fill(dataSet, "Products");
}

public override void Process()


{

Version: 1.0
Side: 215
Project: Design Pattern

Console.WriteLine("Products ---- ");


DataTable dataTable = dataSet.Tables["Products"];
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["ProductName"]);
}
Console.WriteLine();
}
}
}

Output
Categories ----
Beverages
Condiments
Confections
Dairy Products
Grains/Cereals
Meat/Poultry
Produce
Seafood

Products ----
Chai
Chang
Aniseed Syrup
Chef Anton's Cajun Seasoning
Chef Anton's Gumbo Mix
Grandma's Boysenberry Spread
Uncle Bob's Organic Dried Pears
Northwoods Cranberry Sauce
Mishi Kobe Niku

2.3.11 Visitor
Defines a new operation to a class without change

2.3.11.1 Definition
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new
operation without changing the classes of the elements on which it operates.

Version: 1.0
Side: 216
Project: Design Pattern

2.3.11.2 UML class diagram

2.3.11.3 Participants
The classes and/or objects participating in this pattern are:

• Visitor (Visitor)
o declares a Visit operation for each class of ConcreteElement in the object structure. The
operation's name and signature identifies the class that sends the Visit request to the visitor.
That lets the visitor determine the concrete class of the element being visited. Then the
visitor can access the elements directly through its particular interface
• ConcreteVisitor (IncomeVisitor, VacationVisitor)
o implements each operation declared by Visitor. Each operation implements a fragment of
the algorithm defined for the corresponding class or object in the structure. ConcreteVisitor
provides the context for the algorithm and stores its local state. This state often accumulates
results during the traversal of the structure.
• Element (Element)
o defines an Accept operation that takes a visitor as an argument.
• ConcreteElement (Employee)

Version: 1.0
Side: 217
Project: Design Pattern

o implements an Accept operation that takes a visitor as an argument


• ObjectStructure (Employees)
o can enumerate its elements
o may provide a high-level interface to allow the visitor to visit its elements
o may either be a Composite (pattern) or a collection such as a list or a set

2.3.11.4 Sample code In C#


This structural code demonstrates the Visitor pattern in which an object traverses an object
structure and performs the same operation on each node in this structure. Different visitor
objects define different operations.
// Visitor pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Visitor.Structural
{

// MainApp test application

class MainApp
{
static void Main()
{
// Setup structure
ObjectStructure o = new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());

// Create visitor objects


ConcreteVisitor1 v1 = new ConcreteVisitor1();
ConcreteVisitor2 v2 = new ConcreteVisitor2();

// Structure accepting visitors


o.Accept(v1);
o.Accept(v2);

// Wait for user


Console.Read();
}
}

// "Visitor"

abstract class Visitor


{
public abstract void VisitConcreteElementA(
ConcreteElementA concreteElementA);
public abstract void VisitConcreteElementB(
ConcreteElementB concreteElementB);
}

Version: 1.0
Side: 218
Project: Design Pattern

// "ConcreteVisitor1"

class ConcreteVisitor1 : Visitor


{
public override void VisitConcreteElementA(
ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} visited by {1}",
concreteElementA.GetType().Name, this.GetType().Name);
}

public override void VisitConcreteElementB(


ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} visited by {1}",
concreteElementB.GetType().Name, this.GetType().Name);
}
}

// "ConcreteVisitor2"

class ConcreteVisitor2 : Visitor


{
public override void VisitConcreteElementA(
ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} visited by {1}",
concreteElementA.GetType().Name, this.GetType().Name);
}

public override void VisitConcreteElementB(


ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} visited by {1}",
concreteElementB.GetType().Name, this.GetType().Name);
}
}

// "Element"

abstract class Element


{
public abstract void Accept(Visitor visitor);
}

// "ConcreteElementA"

class ConcreteElementA : Element


{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementA(this);
}

public void OperationA()


{

Version: 1.0
Side: 219
Project: Design Pattern

}
}

// "ConcreteElementB"

class ConcreteElementB : Element


{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementB(this);
}

public void OperationB()


{
}
}

// "ObjectStructure"

class ObjectStructure
{
private ArrayList elements = new ArrayList();

public void Attach(Element element)


{
elements.Add(element);
}

public void Detach(Element element)


{
elements.Remove(element);
}

public void Accept(Visitor visitor)


{
foreach (Element e in elements)
{
e.Accept(visitor);
}
}
}
}

Output
ConcreteElementA visited by ConcreteVisitor1
ConcreteElementB visited by ConcreteVisitor1
ConcreteElementA visited by ConcreteVisitor2
ConcreteElementB visited by ConcreteVisitor2

This real-world code demonstrates the Visitor pattern in which two objects traverse a list of
Employees and performs the same operation on each Employee. The two visitor objects
define different operations -- one adjusts vacation days and the other income.

// Visitor pattern -- Real World example

Version: 1.0
Side: 220
Project: Design Pattern

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Visitor.RealWorld
{

// MainApp startup application

class MainApp
{
static void Main()
{
// Setup employee collection
Employees e = new Employees();
e.Attach(new Clerk());
e.Attach(new Director());
e.Attach(new President());

// Employees are 'visited'


e.Accept(new IncomeVisitor());
e.Accept(new VacationVisitor());

// Wait for user


Console.Read();
}
}

// "Visitor"

interface IVisitor
{
void Visit(Element element);
}

// "ConcreteVisitor1"

class IncomeVisitor : IVisitor


{
public void Visit(Element element)
{
Employee employee = element as Employee;

// Provide 10% pay raise


employee.Income *= 1.10;
Console.WriteLine("{0} {1}'s new income: {2:C}",
employee.GetType().Name, employee.Name,
employee.Income);
}
}

// "ConcreteVisitor2"

class VacationVisitor : IVisitor


{
public void Visit(Element element)

Version: 1.0
Side: 221
Project: Design Pattern

{
Employee employee = element as Employee;

// Provide 3 extra vacation days


Console.WriteLine("{0} {1}'s new vacation days: {2}",
employee.GetType().Name, employee.Name,
employee.VacationDays);
}
}

class Clerk : Employee


{
// Constructor
public Clerk() : base("Hank", 25000.0, 14)
{
}
}

class Director : Employee


{
// Constructor
public Director() : base("Elly", 35000.0, 16)
{
}
}

class President : Employee


{
// Constructor
public President() : base("Dick", 45000.0, 21)
{
}
}

// "Element"

abstract class Element


{
public abstract void Accept(IVisitor visitor);
}

// "ConcreteElement"

class Employee : Element


{
string name;
double income;
int vacationDays;

// Constructor
public Employee(string name, double income,
int vacationDays)
{
this.name = name;
this.income = income;
this.vacationDays = vacationDays;

Version: 1.0
Side: 222
Project: Design Pattern

// Properties
public string Name
{
get{ return name; }
set{ name = value; }
}

public double Income


{
get{ return income; }
set{ income = value; }
}

public int VacationDays


{
get{ return vacationDays; }
set{ vacationDays = value; }
}

public override void Accept(IVisitor visitor)


{
visitor.Visit(this);
}
}

// "ObjectStructure"

class Employees
{
private ArrayList employees = new ArrayList();

public void Attach(Employee employee)


{
employees.Add(employee);
}

public void Detach(Employee employee)


{
employees.Remove(employee);
}

public void Accept(IVisitor visitor)


{
foreach (Employee e in employees)
{
e.Accept(visitor);
}
Console.WriteLine();
}
}
}

Output

Version: 1.0
Side: 223
Project: Design Pattern

Clerk Hank's new income: $27,500.00


Director Elly's new income: $38,500.00
President Dick's new income: $49,500.00

Clerk Hank's new vacation days: 14


Director Elly's new vacation days: 16
President Dick's new vacation days: 21

Version: 1.0
Side: 224

You might also like