• No results found

Design Patterns Abap Objects

N/A
N/A
Protected

Academic year: 2021

Share "Design Patterns Abap Objects"

Copied!
224
0
0

Loading.... (view fulltext now)

Full text

(1)

Design Patterns

Implementation Of objects using design

patterns in Abap Object

Version: 1

Date: 2. Januar 2008

(2)

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

(3)

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

(4)

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

(5)

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

(6)

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

(7)

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

(8)

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:

(9)

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.

(10)

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.

(11)

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(); }

(12)

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

(13)

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

(14)

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.

(15)

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.

(16)

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() {

(17)

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"

(18)

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.

(19)

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 .

(20)

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.

(21)

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

(22)

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.

(23)

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"

(24)

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)

(25)

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

(26)

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.

(27)

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();

(28)

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 {

(29)

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"; }

(30)

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

(31)

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.

(32)

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

(33)

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( ).

(34)

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.

(35)

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 {

(36)

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(); }

(37)

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(); }

(38)

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 {

}

(39)

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

(40)

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

(41)

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.

(42)

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.

(43)

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.

References

Related documents

the manufacturing firms in Colombia 17. In view of the fact that EDIT II is a rider of the EAM we can merge both surveys at the firm level which is extremely useful for

The preheat temperature to be applied during fabrication shall not be less than the qualified preheat temperature (i.e.: 0 / +30°C). f) The preheat temperature shall be checked at

Chapter 4 of this dissertation presents the surface chemistry of the chiral probe molecule S-glycidol 6 and it has been demonstrated that glycidol can be used as a potential

Thus stressing the previously addressed issue that the new supply chain-related regulations are very costly, many companies may be expected to make a business case of their

We launched our management division in 1999 and have since operated and maximized profitability for an impressive portfolio of hotels and residential properties on behalf of

Don’t misunderstand, no one denies that the brain receives, stores, and transmits information. But it can’t do these things in anything remotely like the way introspection tells us

The contract considered in this paper is the wholesale price contract model, the wholesale price w is determined by the manufacturer and retailer jointly, and under

In our opinion, the consolidated financial statements give a true and fair view of the financial position of the Group as at 31 December 2013, and of its financial performance and