Design Patterns

Implementation Of objects using design patterns in Abap Object

Version: 1 Date: 2. Januar 2008

Project: Design Pattern

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

Reference documents
Document The Gang Of Four Version Location

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

Version: 1.0 Side: ii

Project: Design Pattern
Contents: 1 2 INTRODUCTION DESIGN PATTERNS 2.1 CREATIONAL PATTERNS 2.1.1 Abstract Factory
2.1.1.1 2.1.1.2 2.1.1.3 2.1.1.4 2.1.1.5 2.1.1.6 2.1.1.7 2.1.1.8 Definition Commen Use UML class diagram Participants Sample code in C# Sample code in ABAP Sample code in C# Sample code in ABAP

6 6 7 7
7 8 10 10 10 13 16 18

2.1.2

Builder
Definition Useful tips UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP

21
21 21 22 22 22 25 27 31

2.1.2.1 2.1.2.2 2.1.2.3 2.1.2.4 2.1.2.5 2.1.2.6 2.1.2.7 2.1.2.8

2.1.3

Factory Method
Definition UML class diagram Participants Sample code In C# Sample code in ABAP Sample code in ABAP Sample code in ABAP

34
34 35 35 35 40 42 44

2.1.3.1 2.1.3.2 2.1.3.3 2.1.3.4 2.1.3.5 2.1.3.6 2.1.3.7

2.1.4

Prototype
Definition Used for UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP

47
47 47 48 48 48 50 52 54

2.1.4.1 2.1.4.2 2.1.4.3 2.1.4.4 2.1.4.5 2.1.4.6 2.1.4.7 2.1.4.8

2.1.5

Singleton
Definition Common Use Implementation UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP Sample code In ABAP for Application

57
57 57 58 59 59 59 60 62 64 66

2.1.5.1 2.1.5.2 2.1.5.3 2.1.5.4 2.1.5.5 2.1.5.6 2.1.5.7 2.1.5.8 2.1.5.9 2.1.5.10

2.2 STRUCTURAL PATTERNS 2.2.1 Adapter
2.2.1.1 2.2.1.2 2.2.1.3 2.2.1.4
Version: 1.0 Side: 3

67 67
67 68 69 69

Definition Common Use UML class diagram Participants

Project: Design Pattern
2.2.1.5 2.2.1.6 2.2.1.7 2.2.1.8 2.2.1.9 Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP Sample code In ABAP using interfaces 69 70 72 75 79

2.2.2

Bridge
Definition Common Use UML class diagram Participants Sample code In C#

83
83 83 84 84 84

2.2.2.1 2.2.2.2 2.2.2.3 2.2.2.4 2.2.2.5

2.2.3

Composite
Definition UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP

84
84 85 85 85 88 91 93

2.2.3.1 2.2.3.2 2.2.3.3 2.2.3.4 2.2.3.5 2.2.3.6 2.2.3.7

2.2.4

Decorator
Definition UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP

96
96 97 97 97 99 102 105

2.2.4.1 2.2.4.2 2.2.4.3 2.2.4.4 2.2.4.5 2.2.4.6 2.2.4.7

2.2.5

Facade
Definition UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP

110
110 110 110 111 113 116 118

2.2.5.1 2.2.5.2 2.2.5.3 2.2.5.4 2.2.5.5 2.2.5.6 2.2.5.7

2.2.6

Flyweight (fluevægt)
Definition UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C#

122
122 122 122 123 124 127

2.2.6.1 2.2.6.2 2.2.6.3 2.2.6.4 2.2.6.5 2.2.6.6

2.2.7

Proxy
Definition UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C# Sample code In ABAP using interface

130
130 131 131 131 133 135 136

2.2.7.1 2.2.7.2 2.2.7.3 2.2.7.4 2.2.7.5 2.2.7.6 2.2.7.7

2.3 BEHAVIORAL PATTERNS 2.3.1 Chain of Resp.
2.3.1.1 2.3.1.2 2.3.1.3 2.3.1.4 2.3.1.5 2.3.1.6
Version: 1.0 Side: 4

139 139
139 140 140 140 142 146

Definition UML class diagram Participants Sample code In C# Sample code In ABAP Sample code In C#

3.6.3 2.3.3 2.2 2.4 2.3.1 2.5.1 2.4.3.5.2 2.4 2.3.2 2.3.10.1 2.2 2.8.9 Strategy Definition UML class diagram Participants Sample code In C# 206 206 207 207 207 2.1 2.4 2.7.6.5.3.3.1 2.8 State Definition UML class diagram Participants Sample code I C# 198 198 198 199 199 2.3 2.10.2 2.7 Observer Definition UML class diagram Participants Sample code I C# 192 192 193 193 193 2.4 2.3.5 2.3.6.3.3.3.3.3.9.2.3 2.7.3.10 2.9.1 2.8.3.3.3.8.3.6.3.4 Iterator Definition UML class diagram Participants Sample code I C# 174 174 174 174 175 2.11.4 2.3.4 2.3.1 2.9.2 2.3.2 Command Definition UML class diagram Participants Sample code In C# Sample code in ABAP Sample code In C# Sample code In C# 154 154 155 155 155 157 160 163 2.11.3 2.3.3.1 2.6 2.9.2 2.10.3.3.2.3.3.3 Interpreter Definition UML class diagram Participants Sample code I C# 169 169 169 169 170 2.3.2.3.3 2.7 Sample code In ABAP 149 2.11.3.3.3.3.11.7.0 Side: 5 .3.2.3.4.3.2 2.3 2.3.4.3.3.3.3 2.3.3.7.2.3.1 2.2.3.5.7 2.6 Memento Definition UML class diagram Participants Sample code I C# 187 187 187 187 187 2.4 2.3.10.Project: Design Pattern 2.4 Visitor Definition UML class diagram Participants Sample code In C# 216 216 217 217 218 Version: 1.3.3.3.4 2.3.3.11 2.3 2.3.1.3 2.2 2.4 Template Method Definition UML class diagram Participants Sample code In C# 211 211 212 212 212 2.3.3.8.4.2 2.5 Mediator Definition UML class diagram Participants Sample code I C# 180 180 181 181 181 2.2.3.1 2.3.

A third form. The Gang of Four (GoF) patterns are generally considered the foundation for all other patterns. the C# source code is provided in 2 forms: 'structural' and 'real-world'. Creational Patterns Abstract Factory Builder Factory Method Prototype Singleton Creates an instance of several families of classes Separates object construction from its representation Creates an instance of several derived classes A fully initialized instance to be copied or cloned A class of which only a single instance can exist Structural Patterns Adapter Bridge Composite Decorator Facade Version: 1. reusable solutions to commonly encountered programming challenges. Here you will find information on these important patterns. Structural. They are categorized in three groups: Creational. as well as providing a communication platform concerning elegant. These design patterns have been copied from The Gang of Four homepage. 'ABAP Object' demonstrates design patterns that exploit SAP R/3 built-in ABAP Object’s features.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. Real-world code provides real-world programming situations where you may use these patterns. and Behavioral.0 Side: 6 Match interfaces of different classes Separates an object’s interface from its implementation A tree structure of simple and composite objects Add responsibilities to objects dynamically A single class that represents an entire subsystem . To give you a head start. Patterns are about design and interaction of objects. Structural code uses type names as defined in the pattern definition and UML diagrams.

1 Abstract Factory Creates an instance of several families of classes 2.1. 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. 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. Version: 1.1 Definition Provide an interface for creating families of related or dependent objects without specifying their concrete classes A software design pattern.Project: Design Pattern Flyweight Proxy A fine-grained instance used for efficient sharing An object representing another object Behavioral Patterns Chain of Resp. In normal usage.1. Command Interpreter Iterator Mediator Memento Observer State Strategy Template Method Visitor A way of passing a request between a chain of objects Encapsulate a command request as an object A way to include language elements in a program Sequentially access the elements of a collection Defines simplified communication between classes Capture and restore an object's internal state A way of notifying change to a number of classes Alter an object's behavior when its state changes Encapsulates an algorithm inside a class Defer the exact steps of an algorithm to a subclass Defines a new operation to a class without change 2. This pattern separates the details of implementation of a set of objects from its general usage.1 Creational Patterns 2. the Abstract Factory Pattern provides a way to encapsulate a group of individual factories that have a common theme.1.0 Side: 7 .

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. In software development.Project: Design Pattern An example of this would be an abstract factory class DocumentCreator that provides interfaces to create a number of products (eg. for instance. Use of this pattern makes it possible to interchange concrete classes without changing the code that uses them. However. As the factory only returns an abstract pointer. This allows for new derived types to be introduced with no change to the code that uses the base class.1.0 Side: 8 . this means: Version: 1. However. by the new operator). and it is here that the object is actually created (in C++. for instance. The client code would get an appropriate instantiation of the DocumentCreator and call its factory methods. createLetter() and createResume()). 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. since it has already been specified in the configuration file. the factory may read it from a configuration file. incurs the risk of unnecessary complexity and extra work in the initial writing of code. However. the client code (which requested the object from the factory) does not know . as with similar design patterns. The system would have any number of derived concrete versions of the DocumentCreator class like FancyDocumentCreator or ModernDocumentCreator. In particular. the factory only returns an abstract pointer to the created concrete object. not the specific version that it got from the concrete factory. Each of these products is derived from a simple abstract class like Letter or Resume of which the client is aware.and is not burdened by . The client would need to know how to handle only the abstract Letter or Resume class. employment of this pattern. the type of a concrete object (and hence a concrete factory) is known by the abstract factory. 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). 2. The client has no need to specify the type.2 Commen Use The factory determines the actual concrete type of object to be created. even at runtime.the actual concrete type of the object which was just created. each with a different implementation of createLetter() and createResume() that would create a corresponding object like FancyLetter or ModernResume.1.

) This is significantly easier than modifying the client code to instantiate a new type. but still returns a pointer of the same abstract type as before . and all client code goes through the singleton to access the proper factory for object creation.0 Side: 9 . then changing factories is as easy as changing the singleton object. If all factory objects are stored globally in a singleton object. The client code deals only with the abstract type. by including for instance a concrete class header file). but the client code accesses such objects only through their abstract interface. not needing to include any header files or class declarations relating to the concrete type. (The different factory then creates objects of a different concrete type. • The class diagram of this design pattern is as shown Version: 1.Project: Design Pattern • The client code has no knowledge whatsoever of the concrete type. a modification which is typically one line in one file.thus insulating the client code from change. 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. Objects of a concrete type are indeed created by the factory. Adding new concrete types is done by modifying the client code to use a different factory.

Object creation has been abstracted and there is no need for hard-coded class names in the client code.1.1.1.Project: Design Pattern 2.0 Side: 10 . // Abstract Factory pattern -. Carnivore) declares an interface for a type of product object • Product (Wildebeest.1.1. Lion.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. 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.Structural example Version: 1.5 Sample code in C# This structural code demonstrates the Abstract Factory pattern creating parallel hierarchies of objects. AmericaFactory) implements the operations to create concrete product objects • AbstractProduct (Herbivore.3 UML class diagram 2.

Run().Abstract.Run().Read(). } } // "AbstractFactory" abstract class AbstractFactory { public abstract AbstractProductA CreateProductA().0 Side: 11 . Client c2 = new Client(factory2). } } // "ConcreteFactory2" class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2().Structural { // MainApp test application class MainApp { public static void Main() { // Abstract factory #1 AbstractFactory factory1 = new ConcreteFactory1(). // Wait for user input Console. Client c1 = new Client(factory1). c1. public abstract AbstractProductB CreateProductB(). } public override AbstractProductB CreateProductB() { return new ProductB1(). // Abstract factory #2 AbstractFactory factory2 = new ConcreteFactory2().Project: Design Pattern using System. } public override AbstractProductB CreateProductB() Version: 1. } // "ConcreteFactory1" class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(). namespace DoFactory. c2.GangOfFour.

Name + " interacts with " + a. } // "ProductA1" class ProductA1 : AbstractProductA { } // "ProductB1" class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console. } } // "ProductA2" class ProductA2 : AbstractProductA { } // "ProductB2" class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.GetType().GetType().GetType(). } } // "AbstractProductA" abstract class AbstractProductA { } // "AbstractProductB" abstract class AbstractProductB { public abstract void Interact(AbstractProductA a).GetType().Name).0 Side: 12 .the interaction environment of the products class Client { Version: 1.WriteLine(this.Project: Design Pattern { return new ProductB2().Name).Name + " interacts with " + a. } } // "Client" .WriteLine(this.

DEFINE ?get_class_name. CLASS cl_abap_typedescr DEFINITION LOAD. In ABAP you should consider using interfaces instead of abstract classes. PUBLIC SECTION.mlen TYPE i. } public void Run() { AbstractProductB. METHODS: interact ABSTRACT IMPORTING a TYPE REF TO abstractproducta . ENDCLASS. AbstractProductA = factory.slen TYPE i .CreateProductA().1. Version: 1. find regex 'CLASS=' in &2 match offset moff match length mlen. private AbstractProductB AbstractProductB.Project: Design Pattern private AbstractProductA AbstractProductA. ENDCLASS.CreateProductB().6 Sample code in ABAP This structural code demonstrates the Abstract Factory pattern creating parallel hierarchies of objects. REPORT ZABSTRACTFACTORY_STRUCTURAL NO STANDARD PAGE HEADING LINE-SIZE 80. "abstractproductb DEFINITION CLASS abstractproductb IMPLEMENTATION. DATA: moff TYPE i . ENDCLASS.1.Interact(AbstractProductA). slen = moff + mlen. shift &2 by slen places left. END-OF-DEFINITION. "abstractproducta DEFINITION CLASS abstractproductb DEFINITION ABSTRACT. // Constructor public Client(AbstractFactory factory) { AbstractProductB = factory. } } } Output ProductB1 interacts with ProductA1 ProductB2 interacts with ProductA2 2.0 Side: 13 . CLASS abstractproducta DEFINITION ABSTRACT. "abstractproductb IMPLEMENTATION CLASS producta1 DEFINITION INHERITING FROM abstractproducta. ENDCLASS. "producta1 DEFINITION CLASS productb1 DEFINITION INHERITING FROM abstractproductb. &2 = cl_abap_classdescr=>get_class_name( &1 ). Object creation has been abstracted and there is no need for hard-coded class names in the client code.

class_name_a. ENDMETHOD. ENDMETHOD.Project: Design Pattern PUBLIC SECTION. DATA: class_name_me TYPE abap_abstypename .createproductb ABSTRACT RETURNING value(productb) TYPE REF TO abstractproductb . ?get_class_name me class_name_me. METHODS: createproducta ABSTRACT RETURNING value(producta) TYPE REF TO abstractproducta . ENDCLASS. ENDMETHOD.'Interact with ' . ?get_class_name a class_name_a. Version: 1. "interact ENDCLASS. PUBLIC SECTION. ?get_class_name a class_name_a. METHODS: interact REDEFINITION. PUBLIC SECTION. METHOD createproducta. METHOD interact.class_name_a. "concretefactory1 IMPLEMENTATION CLASS concretefactory2 DEFINITION INHERITING FROM abstractfactory.'Interact with ' . "concretefactory1 DEFINITION CLASS concretefactory1 IMPLEMENTATION. ENDCLASS.class_name_a TYPE abap_abstypename. "productb1 IMPLEMENTATION CLASS producta2 DEFINITION INHERITING FROM abstractproducta. "productb1 DEFINITION CLASS productb1 IMPLEMENTATION. CREATE OBJECT productb TYPE productb1. ?get_class_name me class_name_me.class_name_a TYPE abap_abstypename. "productb2 IMPLEMENTATION CLASS abstractfactory DEFINITION ABSTRACT.createproductb REDEFINITION . DATA: class_name_me TYPE abap_abstypename . "abstractfactory DEFINITION CLASS concretefactory1 DEFINITION INHERITING FROM abstractfactory. CREATE OBJECT producta TYPE producta1. PUBLIC SECTION. "createproductb ENDCLASS. "productb2 DEFINITION CLASS productb2 IMPLEMENTATION. METHODS: interact REDEFINITION. ENDCLASS. ENDCLASS. PUBLIC SECTION. WRITE: / class_name_me . ENDMETHOD. METHOD interact. METHODS: createproducta REDEFINITION . "createproducta METHOD createproductb. ENDCLASS. "interact ENDCLASS. WRITE: / class_name_me .0 Side: 14 . "producta2 DEFINITION CLASS productb2 DEFINITION INHERITING FROM abstractproductb.

CREATE OBJECT c1 EXPORTING factory = factory1 . ENDMETHOD. ENDCLASS. ENDCLASS.abstractproductb TYPE REF TO abstractproductb . CREATE OBJECT producta TYPE producta2. PROTECTED SECTION. CREATE OBJECT productb TYPE productb2.Project: Design Pattern METHODS: createproducta REDEFINITION . Version: 1. METHOD constructor. concretefactory1 concretefactory2 client client CREATE OBJECT factory1. CREATE OBJECT factory2. START-OF-SELECTION. abstractproductb = factory->createproductb( ). "concretefactory1 IMPLEMENTATION CLASS client DEFINITION. "concretefactory2 DEFINITION CLASS concretefactory2 IMPLEMENTATION. DATA: factory1 TYPE REF TO . "run ENDCLASS. PUBLIC SECTION. ENDMETHOD. METHOD main. ENDMETHOD. ENDCLASS. ENDMETHOD. "constructor METHOD run. mainapp=>main( ). CALL METHOD c2->run( ).createproductb REDEFINITION . "createproducta METHOD createproductb. "mainapp DEFINITION CLASS mainapp IMPLEMENTATION. CREATE OBJECT c2 EXPORTING factory = factory2. METHOD createproducta. PUBLIC SECTION. abstractproductb->interact( abstractproducta ). ENDMETHOD. ENDCLASS. CLASS-METHODS main. CALL METHOD c1->run( ).c1 TYPE REF TO . abstractproducta = factory->createproducta( ). "client IMPLEMENTATION CLASS mainapp DEFINITION.c2 TYPE REF TO . * CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator. "createproductb ENDCLASS.run . "client DEFINITION CLASS client IMPLEMENTATION.0 Side: 15 "main "mainapp IMPLEMENTATION .factory2 TYPE REF TO . METHODS: constructor IMPORTING factory TYPE REF TO abstractfactory . DATA: abstractproducta TYPE REF TO abstractproducta .

1. // Abstract Factory pattern -. world.Real World example using System. world = new AnimalWorld(america). } } // "AbstractFactory" abstract class ContinentFactory { public abstract Herbivore CreateHerbivore(). the interactions among the animals remain the same.RealWorld { // MainApp test application class MainApp { public static void Main() { // Create and run the Africa animal world ContinentFactory africa = new AfricaFactory(). } // "ConcreteFactory1" class AfricaFactory : ContinentFactory { public override Herbivore CreateHerbivore() { Version: 1.Read().0 Side: 16 . namespace DoFactory.7 Sample code in C# This real-world code demonstrates the creation of different animal worlds for a computer game using different factories.GangOfFour. world. // Create and run the America animal world ContinentFactory america = new AmericaFactory().Abstract. // Wait for user input Console. Although the animals created by the Continent factories are different. AnimalWorld world = new AnimalWorld(africa).1.RunFoodChain(). public abstract Carnivore CreateCarnivore().Project: Design Pattern Output PRODUCTB1 Interact with PRODUCTA1 PRODUCTB2 Interact with PRODUCTA2 2.RunFoodChain().

} // "ProductA1" class Wildebeest : Herbivore { } // "ProductB1" class Lion : Carnivore { public override void Eat(Herbivore h) { // Eat Wildebeest Console.GetType(). } } // "ProductA2" class Bison : Herbivore Version: 1.Name + " eats " + h.WriteLine(this. } public override Carnivore CreateCarnivore() { return new Lion().0 Side: 17 . } } // "ConcreteFactory2" class AmericaFactory : ContinentFactory { public override Herbivore CreateHerbivore() { return new Bison().GetType().Project: Design Pattern return new Wildebeest().Name). } } // "AbstractProductA" abstract class Herbivore { } // "AbstractProductB" abstract class Carnivore { public abstract void Eat(Herbivore h). } public override Carnivore CreateCarnivore() { return new Wolf().

} public void RunFoodChain() { carnivore.Name).mlen TYPE i. Although the animals created by the Continent factories are different. the interactions among the animals remain the same. // Constructor public AnimalWorld(ContinentFactory factory) { carnivore = factory. You should however consider using interfaces instead of abstract classes. CLASS cl_abap_typedescr DEFINITION LOAD.slen TYPE i . Version: 1.Eat(herbivore). private Carnivore carnivore.0 Side: 18 . } } // "Client" class AnimalWorld { private Herbivore herbivore. DEFINE ?get_class_name.Project: Design Pattern { } // "ProductB2" class Wolf : Carnivore { public override void Eat(Herbivore h) { // Eat Bison Console. herbivore = factory.CreateCarnivore().CreateHerbivore().1.GetType(). DATA: moff TYPE i .1. } } } Output Lion eats Wildebeest Wolf eats Bison 2.GetType().8 Sample code in ABAP This real-world code demonstrates the creation of different animal worlds for a computer game using different factories.WriteLine(this. REPORT zabstractfactory_realworld NO STANDARD PAGE HEADING LINE-SIZE 80.Name + " eats " + h.

Project: Design Pattern &2 = cl_abap_classdescr=>get_class_name( &1 ). METHODS: eat ABSTRACT IMPORTING a TYPE REF TO herbivore . "carnivore IMPLEMENTATION CLASS wildebeest DEFINITION INHERITING FROM herbivore. "Lion DEFINITION CLASS lion IMPLEMENTATION. ENDCLASS. METHODS: eat REDEFINITION. PUBLIC SECTION. slen = moff + mlen. WRITE: / class_name_me . "Bison DEFINITION CLASS wolf DEFINITION INHERITING FROM carnivore.class_name_a. ENDCLASS. ?get_class_name a class_name_a. METHOD eat. Version: 1. ENDMETHOD. "interact ENDCLASS. find regex 'CLASS=' in &2 match offset moff match length mlen. ?get_class_name a class_name_a. ?get_class_name me class_name_me. "herbivore DEFINITION CLASS carnivore DEFINITION ABSTRACT. WRITE: / class_name_me .class_name_a TYPE abap_abstypename. "interact ENDCLASS.0 Side: 19 .' eats ' .class_name_a. ENDMETHOD. shift &2 by slen places left.class_name_a TYPE abap_abstypename.createcarnivore ABSTRACT RETURNING value(carnivore) TYPE REF TO carnivore . PUBLIC SECTION. ?get_class_name me class_name_me. ENDCLASS. CLASS herbivore DEFINITION ABSTRACT. "Wolf IMPLEMENTATION CLASS continentfactory DEFINITION ABSTRACT. METHOD eat. DATA: class_name_me TYPE abap_abstypename . ENDCLASS. PUBLIC SECTION. "Lion IMPLEMENTATION CLASS bison DEFINITION INHERITING FROM herbivore. ENDCLASS. END-OF-DEFINITION. METHODS: eat REDEFINITION.' eats ' . PUBLIC SECTION. "wildebeest DEFINITION CLASS lion DEFINITION INHERITING FROM carnivore. "Wolf DEFINITION CLASS wolf IMPLEMENTATION. ENDCLASS. ENDCLASS. "carnivore DEFINITION CLASS carnivore IMPLEMENTATION. METHODS: createherbivore ABSTRACT RETURNING value(herbivore) TYPE REF TO herbivore . DATA: class_name_me TYPE abap_abstypename .

METHODS: createherbivore REDEFINITION . METHOD createherbivore. "constructor METHOD runfoodchain.createcarnivore REDEFINITION . "createproducta METHOD createcarnivore. Version: 1.runfoodchain . PROTECTED SECTION. CREATE OBJECT herbivore TYPE bison. ENDCLASS. CREATE OBJECT carnivore TYPE wolf. ENDMETHOD. ENDMETHOD. "ContinentFactory IMPLEMENTATION CLASS americafactory DEFINITION INHERITING FROM continentfactory. CREATE OBJECT carnivore TYPE lion. "concretefactory2 DEFINITION CLASS americafactory IMPLEMENTATION. CLASS-METHODS main. CREATE OBJECT herbivore TYPE wildebeest. ENDCLASS. ENDMETHOD. ENDMETHOD. "Runfoodchain ENDCLASS. ENDCLASS.createcarnivore REDEFINITION . carnivore = factory->createcarnivore( ). PUBLIC SECTION.carnivore TYPE REF TO carnivore . PUBLIC SECTION. "ContinentFactory DEFINITION CLASS africafactory IMPLEMENTATION.Project: Design Pattern ENDCLASS. METHOD constructor. "ContinentFactory DEFINITION CLASS africafactory DEFINITION INHERITING FROM continentfactory. "ContinentFactory IMPLEMENTATION CLASS animalworld DEFINITION. PUBLIC SECTION. herbivore = factory->createherbivore( ). METHODS: createherbivore REDEFINITION . "createproductb ENDCLASS.0 Side: 20 "mainapp DEFINITION . DATA: herbivore TYPE REF TO herbivore . "Animalworld DEFINITION CLASS animalworld IMPLEMENTATION. ENDCLASS. METHODS: constructor IMPORTING factory TYPE REF TO continentfactory . "createproducta METHOD createcarnivore. PUBLIC SECTION. ENDMETHOD. ENDMETHOD. METHOD createherbivore. "Animalworld IMPLEMENTATION CLASS mainapp DEFINITION. "createproductb ENDCLASS. carnivore->eat( herbivore ).

CALL METHOD world->runfoodchain( ). CALL METHOD world->runfoodchain( ). CREATE OBJECT america. DATA: africa TYPE REF TO africafactory . but as far as the • Version: 1.1.1.america TYPE REF TO americafactory . CREATE OBJECT world EXPORTING factory = africa .2. Output LION eats WILDEBEEST WOLF eats BISON "main "mainapp IMPLEMENTATION 2. The Builder Pattern is a software design pattern.1 Definition Separate the construction of a complex object from its representation so that the same construction process can create different representations. Builder returns the product as a final step. The intention is to separate the construction of a complex object from its representation so that the same construction process can create different representations. Abstract Factory emphasizes a family of product objects (either simple or complex). 2.2 Builder Separates object construction from its representation 2. Often. Abstract Factory. Builder Pattern builds Composite pattern. and Prototype can use Singleton in their implementations. METHOD main.0 Side: 21 . a structure pattern.2 Useful tips • Sometimes creational patterns are complementary: Builder can use one of the other patterns to implement which components get built. Builder.world TYPE REF TO animalworld . START-OF-SELECTION. ENDMETHOD. Builder focuses on constructing a complex object step by step. CREATE OBJECT africa. ENDCLASS.Project: Design Pattern CLASS mainapp IMPLEMENTATION.2. CREATE OBJECT world EXPORTING factory = america. mainapp=>main( ).1.

1. 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. more customizable.0 Side: 22 . CarBuilder. Often. designs start out using Factory Method (less complicated. ConcreteBuilder builds the product's internal representation and defines the process by which it's assembled includes classes that define the constituent parts. The construction process can create different object representations and provides a high level of control over the assembly of the objects. more complex) as the designer discovers where more flexibility is needed.5 Sample code In C# This structural code demonstrates the Builder pattern in which complex objects are created in a step-by-step fashion. 2.1. including interfaces for assembling the parts into the final result 2. // Builder pattern -.2.Project: Design Pattern Abstract Factory is concerned. or Builder (more flexible. the product gets returned immediately.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.3 UML class diagram 2. subclasses proliferate) and evolve toward Abstract Factory. • • Builder often builds a Composite. Prototype.2.Structural example Version: 1.1.

Show().Read(). Product p2 = b2.GetResult(). Builder b1 = new ConcreteBuilder1().Builder.GetResult().Collections. using System. p1.Construct(b2). abstract Product GetResult(). // Construct two products director. Product p1 = b1.Project: Design Pattern using System. builder.Construct(b1).Show(). } } // "Director" class Director { // Builder uses a complex series of steps public void Construct(Builder builder) { builder. } } // "Builder" abstract { public public public } class Builder abstract void BuildPartA().GangOfFour. // Wait for user Console. director. Builder b2 = new ConcreteBuilder2().Structural { // MainApp test application public class MainApp { public static void Main() { // Create director and builders Director director = new Director(). // "ConcreteBuilder1" class ConcreteBuilder1 : Builder Version: 1. namespace DoFactory. abstract void BuildPartB().BuildPartB().BuildPartA().0 Side: 23 . p2.

public override void BuildPartA() { product. public void Add(string part) { parts. } public override void BuildPartB() { product.Add("PartX").Add("PartB"). } } // "Product" class Product { ArrayList parts = new ArrayList().0 Side: 24 . } public override Product GetResult() { return product.Project: Design Pattern { private Product product = new Product().WriteLine("\nProduct Parts -------"). } public override Product GetResult() { return product. } } // "ConcreteBuilder2" class ConcreteBuilder2 : Builder { private Product product = new Product().Add("PartA").Add("PartY"). } public override void BuildPartB() { product. public override void BuildPartA() { product. foreach (string part in parts) Version: 1. } public void Show() { Console.Add(part).

The construction process can create different object representations and provides a high level of control over the assembly of the objects. ENDLOOP. ENDMETHOD.buildparta REDEFINITION . ENDCLASS. DATA: parts_line TYPE string. } } } Output Product Parts ------PartA PartB Product Parts ------PartX PartY 2.0 Side: 25 . LOOP AT parts INTO parts_line.Project: Design Pattern Console. "product IMPLEMENTATION CLASS builder DEFINITION ABSTRACT. ENDMETHOD. "builder DEFINITION CLASS concretebuilder1 DEFINITION INHERITING FROM builder. METHODS: add IMPORTING part TYPE string . WRITE: / parts_line.buildpartb REDEFINITION . PUBLIC SECTION.getresult ABSTRACT RETURNING value(product) TYPE REF TO product.2. CLASS product DEFINITION. PUBLIC SECTION.WriteLine(part). "product DEFINITION CLASS product IMPLEMENTATION. "show ENDCLASS. METHODS: buildparta ABSTRACT .show.6 Sample code In ABAP This structural code demonstrates the Builder pattern in which complex objects are created in a step-by-step fashion. ENDCLASS.getresult REDEFINITION Version: 1.buildpartb ABSTRACT . APPEND part TO parts.1. REPORT zbuilder_structural NO STANDARD PAGE HEADING LINE-SIZE 80. DATA: parts TYPE TABLE OF string. WRITE: / 'Product Parts --------'. METHOD add. PUBLIC SECTION. "add METHOD show. METHODS: constructor .

PRIVATE SECTION. "construct ENDCLASS. METHODS: construct IMPORTING builder TYPE REF TO builder. "buildpartb METHOD getresult. "concretebuilder2 IMPLEMENTATION CLASS director DEFINITION. ENDMETHOD. ENDMETHOD.buildpartb REDEFINITION . CREATE OBJECT me->product. CREATE OBJECT me->product. ENDMETHOD. PUBLIC SECTION. METHOD constructor. product->add('PartA'). product->add('PartX'). product->add('PartY'). "director IMPLEMENTATION CLASS mainapp DEFINITION. ENDMETHOD. "concretebuilder1 DEFINITION CLASS concretebuilder1 IMPLEMENTATION. Version: 1. "buildparta METHOD buildpartb. product = me->product. DATA: product TYPE REF TO product. "concretebuilder1 IMPLEMENTATION CLASS concretebuilder2 DEFINITION INHERITING FROM builder.buildparta REDEFINITION . CALL METHOD super->constructor. PUBLIC SECTION. "getresult ENDCLASS. product->add('Partb'). ENDMETHOD. ENDMETHOD. builder->buildpartb( ). ENDMETHOD. CALL METHOD super->constructor. ENDCLASS. "constructor METHOD buildparta. ENDCLASS.Project: Design Pattern . METHOD constructor. METHOD construct. ENDMETHOD. ENDMETHOD. product = me->product. "director DEFINITION CLASS director IMPLEMENTATION. "concretebuilder2 DEFINITION CLASS concretebuilder2 IMPLEMENTATION. ENDCLASS.0 Side: 26 . CLASS-METHODS main. DATA: product TYPE REF TO product. METHODS: constructor . CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator. PRIVATE SECTION. builder->buildparta( ). "getresult ENDCLASS. "buildparta METHOD buildpartb.getresult REDEFINITION . "constructor METHOD buildparta. PUBLIC SECTION. "buildpartb METHOD getresult.

Real World example using System. mainapp=>main( ).p1 TYPE REF .b2 TYPE REF . Output Product Parts PartA Partb Product Parts PartX PartY "main "mainapp IMPLEMENTATION 2.Builder. The Shop uses VehicleBuilders to construct a variety of Vehicles in a series of sequential steps. // Builder pattern -.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. p2 = b2->getresult( ). ENDMETHOD. METHOD main. ENDCLASS. Version: 1. using System. FIELD-SYMBOLS <fs> TYPE ANY.1. CREATE OBJECT b1. CALL METHOD director->construct( b2 ).p2 TYPE REF . CREATE OBJECT b2.Collections. p1 = b1->getresult( ). p2->show( ). namespace DoFactory. TO TO TO TO TO director concretebuilder1 concretebuilder2 product product CREATE OBJECT director.b1 TYPE REF .Project: Design Pattern ENDCLASS. "mainapp DEFINITION CLASS mainapp IMPLEMENTATION.RealWorld { // MainApp test application public class MainApp { public static void Main() { // Create shop with vehicle builders Shop shop = new Shop().0 Side: 27 .GangOfFour.2. p1->show( ). START-OF-SELECTION. CALL METHOD director->construct( b1 ). DATA: director TYPE REF .

// Property public Vehicle Vehicle { get{ return vehicle.Project: Design Pattern VehicleBuilder b1 = new ScooterBuilder(). BuildDoors().Vehicle. .Show(). } } // "Builder" abstract class VehicleBuilder { protected Vehicle vehicle. vehicleBuilder. } } // "Director" class Shop { // Builder uses a complex series of steps public void Construct(VehicleBuilder vehicleBuilder) { vehicleBuilder. VehicleBuilder b2 = new CarBuilder().Vehicle.0 Side: 28 abstract abstract abstract abstract void void void void BuildFrame(). BuildWheels(). b1.Show().Read().BuildFrame(). // Wait for user Console. BuildEngine(). VehicleBuilder b3 = new MotorCycleBuilder().Construct(b2).Show(). vehicleBuilder.BuildEngine(). b3.Construct(b3). } } public public public public } // "ConcreteBuilder1" class MotorCycleBuilder : VehicleBuilder { public override void BuildFrame() Version: 1.Vehicle.Construct(b1). vehicleBuilder. shop.BuildDoors(). shop. // Construct and display vehicles shop.BuildWheels(). b2.

} public override void BuildWheels() { vehicle["wheels"] = "2". } public override void BuildDoors() { vehicle["doors"] = "0". } public override void BuildEngine() { vehicle["engine"] = "500 cc". } Version: 1.Project: Design Pattern { vehicle = new Vehicle("MotorCycle"). vehicle["frame"] = "Scooter Frame".0 Side: 29 . vehicle["frame"] = "MotorCycle Frame". } public override void BuildEngine() { vehicle["engine"] = "2500 cc". } public override void BuildWheels() { vehicle["wheels"] = "4". } } // "ConcreteBuilder2" class CarBuilder : VehicleBuilder { public override void BuildFrame() { vehicle = new Vehicle("Car"). } } // "ConcreteBuilder3" class ScooterBuilder : VehicleBuilder { public override void BuildFrame() { vehicle = new Vehicle("Scooter"). vehicle["frame"] = "Car Frame". } public override void BuildDoors() { vehicle["doors"] = "4".

} // Indexer (i. private Hashtable parts = new Hashtable(). } set{ parts[key] = value.WriteLine("\n---------------------------").WriteLine(" Frame : {0}". Console. } public override void BuildDoors() { vehicle["doors"] = "0". smart array) public object this[string key] { get{ return parts[key]. Console.WriteLine(" #Doors : {0}". } } // "Product" class Vehicle { private string type.type = type. Console. } } public void Show() { Console.WriteLine("Vehicle Type: {0}". parts["wheels"]). } public override void BuildWheels() { vehicle["wheels"] = "2".0 Side: 30 .Project: Design Pattern public override void BuildEngine() { vehicle["engine"] = "50 cc".WriteLine(" Engine : {0}". } } } Output --------------------------Vehicle Type: Scooter Frame : Scooter Frame Engine : none #Wheels: 2 #Doors : 0 Version: 1.WriteLine(" #Wheels: {0}". Console. Console. parts["doors"]). parts["frame"]). type).e. // Constructor public Vehicle(string type) { this. parts["engine"]).

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. "constructor METHOD add.END OF ty_parts.ty_part(30) TYPE c .show.key TYPE ty_key . parts_line-part. ENDMETHOD. buffer-key = key.BEGIN OF ty_parts .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.part TYPE ty_part . Version: 1. ENDLOOP. TYPES: ty_key(30) TYPE c .vtype(30) TYPE c.add IMPORTING key TYPE ty_key part TYPE ty_part . ENDMETHOD. LOOP AT parts INTO parts_line. CLASS vehicle DEFINITION. INSERT buffer INTO TABLE parts. "Vehicle DEFINITION CLASS vehicle IMPLEMENTATION. WRITE: / 'Vehicle Type:' . DATA: parts_line TYPE ty_parts. METHOD constructor.1. ENDCLASS. "add METHOD show. PRIVATE SECTION. vtype.0 Side: 31 . buffer-part = part. DATA: buffer TYPE ty_parts. DATA: parts TYPE HASHED TABLE OF ty_parts WITH UNIQUE KEY key .2. WRITE: / parts_line-key. METHODS: constructor IMPORTING vtype TYPE string . write: / '---------------------------------------------'. The Shop uses VehicleBuilders to construct a variety of Vehicles in a series of sequential steps. PUBLIC SECTION. me->vtype = vtype. REPORT zbuilder_realworld NO STANDARD PAGE HEADING LINE-SIZE 80.

DATA: vehicle TYPE REF TO vehicle. "Motorcycle DEFINITION CLASS motorcyclebuilder IMPLEMENTATION. CREATE OBJECT vehicle EXPORTING vtype = vtype. ENDMETHOD. METHODS: constructor IMPORTING vtype TYPE string . vehicle->add( EXPORTING key = 'doors' part = '0' ) . ENDMETHOD. PUBLIC SECTION. ENDCLASS. METHOD buildframe.buildframe ABSTRACT . CREATE OBJECT vehicle EXPORTING vtype = 'MotorCycle'. ENDCLASS. vehicle->add( EXPORTING key = 'frame' part = 'Motorcycle Frame' ).buildengine REDEFINITION . ENDCLASS. "builder DEFINITION CLASS vehiclebuilder IMPLEMENTATION. METHOD show. METHODS: buildframe REDEFINITION .builddoors REDEFINITION .buildengine ABSTRACT .0 Side: 32 . PUBLIC SECTION. METHOD constructor.show. vehicle->add( EXPORTING key = 'wheels' part = '2' ) .Project: Design Pattern ENDMETHOD. METHODS: buildframe REDEFINITION . ENDMETHOD. PROTECTED SECTION. vehicle->show( ). "buildpartb METHOD buildwheels. "constructor METHOD getvehicle. vehicle = me->vehicle.buildwheels ABSTRACT . "buildwheels METHOD builddoors. "Motorcycle IMPLEMENTATION CLASS carbuilder DEFINITION INHERITING FROM vehiclebuilder. "show "Vehicle IMPLEMENTATION CLASS vehiclebuilder DEFINITION ABSTRACT.buildwheels REDEFINITION . "builddoors ENDCLASS. "buildparta METHOD buildengine.getvehicle RETURNING value(vehicle) TYPE REF TO vehicle .buildwheels REDEFINITION Version: 1. ENDMETHOD. "vehicle "show "vehiclebuilder IMPLEMENTATION CLASS motorcyclebuilder DEFINITION INHERITING FROM vehiclebuilder. ENDCLASS. ENDMETHOD. ENDMETHOD. ENDMETHOD.builddoors ABSTRACT . vehicle->add( EXPORTING key = 'engine' part = '500 cc' ).buildengine REDEFINITION . PUBLIC SECTION.

METHOD construct. "Carbuilder IMPLEMENTATION CLASS shop DEFINITION. vehicle->add( EXPORTING key = 'wheels' part = '2' ) . "buildpartb METHOD buildwheels.0 Side: 33 . CREATE OBJECT vehicle EXPORTING vtype = 'Scooter'.builddoors . "buildpartb METHOD buildwheels. ENDMETHOD.buildwheels REDEFINITION . ENDCLASS. METHODS: construct IMPORTING vehiclebuilder TYPE REF TO vehiclebuilder. vehicle->add( EXPORTING key = 'frame' part = 'Scooter Frame' ). "buildparta METHOD buildengine. "shop DEFINITION CLASS shop IMPLEMENTATION. "Carbuilder IMPLEMENTATION CLASS scooterbuilder DEFINITION INHERITING FROM vehiclebuilder.buildengine REDEFINITION . vehicle->add( EXPORTING key = 'doors' part = '0' ) . vehiclebuilder->buildframe( ). "Scooterbuilder DEFINITION CLASS scooterbuilder IMPLEMENTATION. ENDMETHOD. ENDMETHOD. ENDMETHOD. ENDMETHOD. "buildwheels METHOD builddoors. ENDCLASS. vehicle->add( EXPORTING key = 'wheels' part = '4' ) . METHOD buildframe. vehiclebuilder->buildengine( ). ENDMETHOD. "buildparta METHOD buildengine. "builddoors ENDCLASS. METHODS: buildframe REDEFINITION . METHOD buildframe. CREATE OBJECT vehicle EXPORTING vtype = 'Car'. "buildwheels METHOD builddoors. PUBLIC SECTION. ENDCLASS. vehicle->add( EXPORTING key = 'engine' part = '50 cc' ). vehicle->add( EXPORTING key = 'doors' part = '4' ) . "builddoors ENDCLASS. vehicle->add( EXPORTING key = 'frame' part = 'Car Frame' ). vehicle->add( EXPORTING key = 'engine' part = '2500 cc' ). ENDMETHOD. ENDMETHOD. Version: 1. PUBLIC SECTION.Project: Design Pattern .builddoors REDEFINITION . REDEFINITION "Carbuilder DEFINITION CLASS carbuilder IMPLEMENTATION.

PUBLIC SECTION. CLASS-METHODS main. CALL METHOD shop->construct( b2 ). Vehicle Type: Scooter frame engine wheels doors Vehicle Type: Car frame engine wheels doors Vehicle Type: MotorCycle frame engine wheels doors Scooter Frame 50 cc 2 0 Car Frame 2500 cc 4 4 Motorcycle Frame 500 cc 2 0 2.b3 TYPE REF TO motorcyclebuilder . * Create shop with vehiclle builders CREATE OBJECT shop.Project: Design Pattern vehiclebuilder->buildwheels( ). CREATE OBJECT b1 EXPORTING vtype = 'Scooter'.1.1 Definition Define an interface for creating an object. vehiclebuilder->builddoors( ).b2 TYPE REF TO carbuilder . b3->show( ).3. CREATE OBJECT b2 EXPORTING vtype = 'Car'. METHOD main. ENDMETHOD. "main "mainapp IMPLEMENTATION ENDMETHOD.b1 TYPE REF TO scooterbuilder . "construct ENDCLASS. CALL METHOD shop->construct( b3 ). * Construct and display vehicles CALL METHOD shop->construct( b1 ). but let subclasses decide which class to instantiate. START-OF-SELECTION.3 Factory Method Creates an instance of several derived classes 2. "shop IMPLEMENTATION CLASS mainapp DEFINITION.1. b2->show( ). ENDCLASS. CREATE OBJECT b3 EXPORTING vtype = 'MotorCycle'.0 Side: 34 . DATA: shop TYPE REF TO shop . Factory Method lets a class defer instantiation to subclasses. mainapp=>main( ). ENDCLASS. Version: 1. "mainapp DEFINITION CLASS mainapp IMPLEMENTATION. CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator. b1->show( ).

ExperiencePage) o implements the Product interface o Creator (Document) o declares the factory method.2 UML class diagram The product is a generelization of the concrete product. like the creator is a generelization of the spacialized concretecreator. but each subclass can instantiate an extended version of the object. The ConcreteCreator have dependency off Product Class 2. namespace DoFactory.Factory. which returns an object of type Product.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.4 Sample code In C# This structural code demonstrates the Factory method offering great flexibility in creating different objects. Creator may also define a default implementation of the factory method that returns a default ConcreteProduct object. // Factory Method pattern -.Collections. The Abstract class may provide a default object. Resume) o overrides the factory method to return an instance of a ConcreteProduct.Structural example using System.3.Project: Design Pattern 2.Structural { // MainApp test application Version: 1. using System.3. o ConcreteCreator (Report.1.1.1. 2.3.0 Side: 35 . may call the factory method to create a Product object.GangOfFour. EducationPage.

} Version: 1.WriteLine("Created {0}".0 Side: 36 .Project: Design Pattern class MainApp { static void Main() { // An array of creators Creator[] creators = new Creator[2].Read(). // Iterate over creators and create products foreach(Creator creator in creators) { Product product = creator. Console.Name). } // "ConcreteCreator" class ConcreteCreatorA : Creator { public override Product FactoryMethod() { return new ConcreteProductA(). } } // "Product" abstract class Product { } // "ConcreteProductA" class ConcreteProductA : Product { } // "ConcreteProductB" class ConcreteProductB : Product { } // "Creator" abstract class Creator { public abstract Product FactoryMethod().GetType(). } // Wait for user Console. creators[1] = new ConcreteCreatorB().FactoryMethod(). creators[0] = new ConcreteCreatorA(). product.

Name).GetType(). namespace DoFactory. // Display document pages foreach (Document document in documents) { Console. documents[1] = new Report().Project: Design Pattern } // "ConcreteCreator" class ConcreteCreatorB : Creator { public override Product FactoryMethod() { return new ConcreteProductB().Real World example using System.Collections.RealWorld { // MainApp test application class MainApp { static void Main() { // Note: constructors call Factory Method Document[] documents = new Document[2]. // Factory Method pattern -. Here. } } } Output Created ConcreteProductA Created ConcreteProductB This real-world code demonstrates the Factory method offering flexibility in creating different documents. } } Version: 1. documents[0] = new Resume().WriteLine(" " + page.Read().GetType().Factory.Name+ "--").GangOfFour.WriteLine("\n" + document.0 Side: 37 . The derived Document classes Report and Resume instantiate extended versions of the Document class. using System. the Factory Method is called in the constructor of the Document base class. } } // Wait for user Console. foreach (Page page in document.Pages) { Console.

0 Side: 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 { } // "Creator" Version: 1.

} public ArrayList Pages { get{ return pages. Pages. Pages.Add(new ResultsPage()).0 Side: 39 .Project: Design Pattern abstract class Document { private ArrayList pages = new ArrayList().Add(new EducationPage()). } // "ConcreteCreator" class Resume : Document { // Factory Method implementation public override void CreatePages() { Pages. Pages.Add(new IntroductionPage()).Add(new SkillsPage()).Add(new SummaryPage()). // Constructor calls abstract Factory method public Document() { this.Add(new ConclusionPage()).CreatePages(). } } } Output Resume ------SkillsPage EducationPage ExperiencePage Report ------IntroductionPage Version: 1. Pages. } } // "ConcreteCreator" class Report : Document { // Factory Method implementation public override void CreatePages() { Pages.Add(new BibliographyPage()). Pages. Pages.Add(new ExperiencePage()). } } // Factory Method public abstract void CreatePages().

1. data: moff type i . shift &2 by slen places left. In ABAP Classes you can’t get the classname with build in functions. CLASS product DEFINITION DEFERRED.3. "product DEFINITION CLASS concreteproducta DEFINITION INHERITING FROM product. ENDCLASS. &2 = cl_abap_classdescr=>get_class_name( &1 ). "concreteproductB DEFINITION Version: 1. slen = moff + mlen. END-OF-DEFINITION. find regex 'CLASS=' in &2 match offset moff match length mlen. DEFERRED. Using a standard SAP class we are able to get the class name. slen = moff + mlen. The Abstract class may provide a default object. CLASS CLASS CLASS CLASS creator concretecreatora concretecreatorb cl_abap_typedescr DEFINITION DEFINITION DEFINITION DEFINITION DEFERRED. "concreteproducta DEFINITION CLASS concreteproductb DEFINITION INHERITING FROM product. CLASS concreteproducta DEFINITION DEFERRED. REPORT zfactory_structural NO STANDARD PAGE HEADING LINE-SIZE 80. and therefore you need to know which class you are working with. LOAD. but each subclass can instantiate an extended version of the object. but sometimes when you process collection of classes you need to do dependent class processes. END-OF-DEFINITION.0 Side: 40 .slen type i . DEFINE ?get_class_name. CLASS product DEFINITION ABSTRACT. In the examples I have build this code into a macro for easy use: * Macro Definition DEFINE ?get_class_name.Project: Design Pattern ResultsPage ConclusionPage SummaryPage BibliographyPage 2. ENDCLASS. DEFERRED.Often you don’t need The classname. * Call macro with parameter <instans object> <returning name> ?get_class_name product class_name. shift &2 by slen places left.mlen type i. ENDCLASS. &2 = cl_abap_classdescr=>get_class_name( &1 ). CLASS concreteproductb DEFINITION DEFERRED . find regex 'CLASS=' in &2 match offset moff match length mlen.5 Sample code in ABAP This structural code demonstrates the Factory method offering great flexibility in creating different objects.

CREATE OBJECT product TYPE concreteproductb. ENDCLASS. METHOD factorymethod. CREATE OBJECT product TYPE concreteproducta. PUBLIC SECTION. DATA: creator TYPE REF TO creator . CASE class_name.concretecreatorb TYPE REF TO concretecreatorb .0 Side: 41 . WRITE: / 'Product ='. METHODS: factorymethod REDEFINITION. product = creator->factorymethod( ). ?get_class_name product class_name. METHODS: factorymethod ABSTRACT RETURNING value(product) TYPE REF TO product. ENDCLASS. ENDMETHOD. APPEND concretecreatora TO oa_creator_coll. CLASS-METHODS main. METHOD main. WRITE: / 'ConcreteCreatorA Creates Product A'. FIELD-SYMBOLS <fs> TYPE ANY.concretecreatora TYPE REF TO concretecreatora .product TYPE REF TO product . "product DEFINITION CLASS concretecreatora DEFINITION INHERITING FROM creator. ?get_class_name <fs> class_name. PUBLIC SECTION. Version: 1. METHODS: factorymethod REDEFINITION. "concretecreatora DEFINITION CLASS concretecreatora IMPLEMENTATION. "factoryproduct ENDCLASS. "concretecreatorb DEFINITION CLASS concretecreatorb IMPLEMENTATION. "concretecreatorb IMPLEMENTATION CLASS mainapp DEFINITION. creator = <fs>. PUBLIC SECTION. APPEND concretecreatorb TO oa_creator_coll. WHEN 'CONCRETECREATORA'. WHEN 'CONCRETECREATORB'. ENDMETHOD. ENDCLASS. "mainapp DEFINITION CLASS mainapp IMPLEMENTATION. "factoryproduct ENDCLASS.class_name. CREATE OBJECT concretecreatora. WRITE: / 'ConcreteCreatorB Creates Product B'. LOOP AT oa_creator_coll ASSIGNING <fs>.class_name TYPE abap_abstypename . "concretecreatora IMPLEMENTATION CLASS concretecreatorb DEFINITION INHERITING FROM creator. ENDLOOP. ENDCASE. ENDCLASS. PUBLIC SECTION. METHOD factorymethod. CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator.Project: Design Pattern CLASS creator DEFINITION ABSTRACT. CREATE OBJECT concretecreatorb.

DEFINE ?get_class_name. "concreteproducta DEFINITION CLASS concreteproducta IMPLEMENTATION.mlen TYPE i. In this example the Abstract class have been replaced by using interfaces. CLASS concreteproducta DEFINITION. DATA: name TYPE ty_productname. &2 = cl_abap_classdescr=>get_class_name( &1 ). ENDMETHOD.3. ENDINTERFACE. "concreteproducta IMPLEMENTATION CLASS concreteproductb DEFINITION. "product~getname ENDCLASS. ENDCLASS. CLASS cl_abap_typedescr DEFINITION LOAD.slen TYPE i . INTERFACES: product. name = 'ConcreteProductA'. mainapp=>main( ). DATA: moff TYPE i . INTERFACE product. shift &2 by slen places left.6 Sample code in ABAP This structural code demonstrates the Factory method offering great flexibility in creating different objects. START-OF-SELECTION. REPORT zfactory_structural NO STANDARD PAGE HEADING LINE-SIZE 80.1. Version: 1. ENDCLASS. slen = moff + mlen.Project: Design Pattern ENDMETHOD. METHOD product~get_name. TYPES ty_productname(30) TYPE c. 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. "main "mainapp IMPLEMENTATION Output ConcreteCreatorA Creates ProductA Product = CONCRETEPRODUCTA ConcreteCreatorB Creates ProductB Product = CONCRETEPRODUCTB 2. END-OF-DEFINITION. PUBLIC SECTION. find regex 'CLASS=' in &2 match offset moff match length mlen.0 Side: 42 . METHODS: get_name RETURNING value(name) TYPE ty_productname.

"concretecreatora IMPLEMENTATION CLASS concretecreatorb DEFINITION. "product~getname ENDCLASS. CLASS concretecreatora DEFINITION. ENDMETHOD. PUBLIC SECTION. METHOD product~get_name. "concretecreatorb DEFINITION CLASS concretecreatorb IMPLEMENTATION. CLASS-DATA: oa_creator_coll TYPE TABLE OF REF TO creator. "concretecreatora DEFINITION CLASS concretecreatora IMPLEMENTATION.product TYPE . "concreteproductB IMPLEMENTATION INTERFACE creator. LOOP AT oa_creator_coll ASSIGNING <fs>. APPEND concretecreatorb TO oa_creator_coll. "concretecreatorb IMPLEMENTATION CLASS mainapp DEFINITION. PUBLIC SECTION. ENDMETHOD. METHOD creator~factorymethod. name = 'ConCreteProductB'.Project: Design Pattern PUBLIC SECTION. APPEND concretecreatora TO oa_creator_coll. CLASS-METHODS main. ENDMETHOD. METHOD main. PUBLIC SECTION. "factoryproduct ENDCLASS. ENDCLASS. CREATE OBJECT concretecreatora. data: concretecreatora TYPE . METHODS: factorymethod RETURNING value(product) TYPE REF TO product. "factoryproduct ENDCLASS. Version: 1.concretecreatorb TYPE . CREATE OBJECT product TYPE concreteproductb. INTERFACES: product. "concreteproductB DEFINITION CLASS concreteproductb IMPLEMENTATION.product_name(30) type . INTERFACES: creator. CREATE OBJECT concretecreatorb. ENDCLASS.class_name TYPE . CREATE OBJECT product TYPE concreteproducta. ENDINTERFACE. INTERFACES: creator. FIELD-SYMBOLS <fs> TYPE REF REF TO concretecreatora REF TO concretecreatorb REF TO product c abap_abstypename TO creator. METHOD creator~factorymethod.0 Side: 43 . "mainapp DEFINITION CLASS mainapp IMPLEMENTATION. * Call macro to find out which Creator and Product are active ?get_class_name <fs> class_name. ENDCLASS. ENDCLASS.

ENDCLASS. REPORT zfactory_structural NO STANDARD PAGE HEADING LINE-SIZE 80. mainapp=>main( ). WRITE: / 'ConcreteCreatorB Creates Product B'. &2 = cl_abap_classdescr=>get_class_name( &1 ). ENDMETHOD.product_name.0 Side: 44 . WHEN 'CONCRETECREATORA'. Here. product_name = product->get_name( ). WRITE: / 'Class= '.Project: Design Pattern CASE class_name. "main "mainapp IMPLEMENTATION Output ConcreteCreatorA Creates ProductA Class = CONCRETEPRODUCTA Product = ConcreteProductA ConcreteCreatorB Creates ProductB Class = CONCRETEPRODUCTB Product = ConcreteProductB 2. ENDLOOP. The derived Document classes Report and Resume instantiate extended versions of the Document class. WHEN 'CONCRETECREATORB'. slen = moff + mlen.7 Sample code in ABAP This real-world code demonstrates the Factory method offering flexibility in creating different documents.'Product ='. in ABAP you cannot call an abstract method from the abstract base class constructor. DATA: moff TYPE i . END-OF-DEFINITION. "page DEFINITION CLASS skillspage DEFINITION INHERITING FROM page. START-OF-SELECTION. WRITE: / 'ConcreteCreatorA Creates Product A'. Version: 1. ENDCLASS.mlen TYPE i. shift &2 by slen places left. class_name. CLASS cl_abap_typedescr DEFINITION LOAD. the Factory Method is called in the constructor of the Document derived class. "skillspage DEFINITION CLASS educationpage DEFINITION INHERITING FROM page.1. ?get_class_name product class_name. CLASS page DEFINITION ABSTRACT.slen TYPE i . product = <fs>->factorymethod( ) . find regex 'CLASS=' in &2 match offset moff match length mlen. ENDCLASS. ENDCASE.3. DEFINE ?get_class_name.

ENDCLASS. "createpages "resume IMPLEMENTATION Version: 1. ENDCLASS. METHODS: constructor . "educationpage DEFINITION CLASS experiencepage DEFINITION INHERITING FROM page. PROTECTED SECTION. METHOD constructor.0 Side: 45 . METHOD pages. ENDCLASS. APPEND page TO oa_pages_coll. CALL METHOD me->createpages. DATA: oa_pages_coll TYPE TABLE OF REF TO page.Project: Design Pattern ENDCLASS. CREATE OBJECT page TYPE experiencepage. ENDCLASS. "conclusionpage DEFINITION CLASS summarypage DEFINITION INHERITING FROM page. ENDCLASS. APPEND page TO oa_pages_coll. ENDMETHOD. "introductionpage DEFINITION CLASS resultspage DEFINITION INHERITING FROM page. "resume DEFINITION CLASS resume IMPLEMENTATION.createpages REDEFINITION. ENDMETHOD. ENDCLASS. "document DEFINITION CLASS document IMPLEMENTATION. ENDCLASS. DATA: page TYPE REF TO page. ENDCLASS. "summarypage DEFINITION CLASS bibliographypage DEFINITION INHERITING FROM page. "bibliographypage DEFINITION CLASS document DEFINITION ABSTRACT. ENDCLASS. APPEND page TO oa_pages_coll. pages[] = oa_pages_coll[]. PUBLIC SECTION.pages EXPORTING pages TYPE ANY TABLE . CREATE OBJECT page TYPE educationpage. ENDCLASS. "pages "document IMPLEMENTATION CLASS resume DEFINITION INHERITING FROM document. ENDMETHOD. METHODS: createpages ABSTRACT . CREATE OBJECT page TYPE skillspage. "constructor METHOD createpages. super->constructor( ). "experiencepage DEFINITION CLASS introductionpage DEFINITION INHERITING FROM page. PUBLIC SECTION. "resultspage DEFINITION CLASS conclusionpage DEFINITION INHERITING FROM page.

PUBLIC SECTION. ENDCLASS. ENDCLASS. CALL METHOD me->createpages.createpages REDEFINITION. CREATE OBJECT page TYPE introductionpage. CREATE OBJECT report. * * 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.page TYPE REF TO page . "mainapp DEFINITION CLASS mainapp IMPLEMENTATION. WHEN 'RESUME'. WRITE: / 'Resume contains following pages:'. CALL METHOD <fs_document>->pages( IMPORTING pages = pages_coll ). APPEND page TO oa_pages_coll. CREATE OBJECT page TYPE summarypage. ENDMETHOD. "report DEFINITION CLASS report IMPLEMENTATION. Loop at all pages in document Resume * Version: 1. FIELD-SYMBOLS: <fs_document> TYPE REF TO document . APPEND resume TO oa_document_coll. DATA: document TYPE REF TO document .resume TYPE REF TO resume . METHOD main. CLASS-DATA: oa_document_coll TYPE TABLE OF REF TO document.0 Side: 46 .Project: Design Pattern CLASS report DEFINITION INHERITING FROM document.<fs_page> TYPE REF TO page. . "constructor METHOD createpages. APPEND page TO oa_pages_coll. CLASS-METHODS main.pages_coll TYPE TABLE OF REF TO page. CREATE OBJECT resume. METHOD constructor. super->constructor( ). APPEND page TO oa_pages_coll. METHODS: constructor . APPEND page TO oa_pages_coll. CREATE OBJECT page TYPE conclusionpage. ENDMETHOD. APPEND report TO oa_document_coll. DATA: page TYPE REF TO page. CREATE OBJECT page TYPE bibliographypage. ENDCLASS. APPEND page TO oa_pages_coll. / sy-uline. PUBLIC SECTION.report TYPE REF TO report .class_name TYPE abap_abstypename . CASE class_name. "createpages "report IMPLEMENTATION CLASS mainapp DEFINITION. CREATE OBJECT page TYPE resultspage.

WRITE: / class_name. CALL METHOD <fs_document>->pages( IMPORTING pages = pages_coll ). ENDLOOP.4.1. ENDCLASS. WRITE: / 'Report contains following pages:'. ENDLOOP. ?get_class_name <fs_page> class_name.2 Used for Prototype pattern is usally used to create objects when the process of object creation is time consuming when done from scratch.4 Prototype A fully initialized instance to be copied or cloned 2.1. Loop at all pages in document Resume LOOP AT pages_coll ASSIGNING <fs_page>.1.0 Side: 47 . mainapp=>main( ). / sy-uline.Project: Design Pattern LOOP AT pages_coll ASSIGNING <fs_page>. ?get_class_name <fs_page> class_name.1 Definition Specify the kind of objects to create using a prototypical instance. WHEN 'REPORT'. START-OF-SELECTION. WRITE: / class_name. ENDCASE. "main "mainapp IMPLEMENTATION * ENDMETHOD. In this case an existing object is used as an prototype and similar objects are constructed using this prototype (without using constructor) Version: 1. and create new objects by copying this prototype.4. ENDLOOP. 2. Output: Resume contains following pages: SKILLSPAGE EDUCATIONPAGE EXPERIENCEPAGE Report contains following pages: INTRODUCTIONPAGE RESULTSPAGE CONCLUSIONPAGE SUMMARYPAGE BIBLIOGRAPHYPAGE 2.

// Prototype pattern -.Project: Design Pattern 2.1. ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone(). namespace DoFactory.Id).3 UML class diagram 2.4.Structural example using System.1.Structural { // MainApp test application class MainApp { static void Main() { // Create two instances and clone each ConcretePrototype1 p1 = new ConcretePrototype1("I").0 Side: 48 .4.Prototype.WriteLine ("Cloned: {0}".4. Console. Version: 1. c1.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.GangOfFour.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.

// Wait for user Console.0 Side: 49 . } } // "ConcretePrototype2" class ConcretePrototype2 : Prototype { // Constructor public ConcretePrototype2(string id) : base(id) { } Version: 1. c2.MemberwiseClone().Clone().id = id.Project: Design Pattern ConcretePrototype2 p2 = new ConcretePrototype2("II"). } } public abstract Prototype Clone(). } } // "Prototype" abstract class Prototype { private string id. } // Property public string Id { get{ return id. ConcretePrototype2 c2 = (ConcretePrototype2)p2. // Constructor public Prototype(string id) { this.WriteLine ("Cloned: {0}".Id).Read(). } // "ConcretePrototype1" class ConcretePrototype1 : Prototype { // Constructor public ConcretePrototype1(string id) : base(id) { } public override Prototype Clone() { // Shallow copy return (Prototype)this. Console.

METHOD constructor. id = me->id.4.get_id RETURNING value(id) TYPE string . METHODS: constructor IMPORTING id TYPE string .MemberwiseClone().Project: Design Pattern public override Prototype Clone() { // Shallow copy return (Prototype)this. PUBLIC SECTION. me->id = id. We uses UP CASTING where the code can’t be checked before runtime. "prototype DEFINITION *----------------------------------------------------------------------* * CLASS prototype IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS prototype IMPLEMENTATION. DATA: id TYPE string. "constructor METHOD get_id.1. ENDMETHOD.clone ABSTRACT RETURNING value(prototype) TYPE REF TO prototype . PRIVATE SECTION.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. } } } Output Cloned: I Cloned: II 2. ENDCLASS. Version: 1.0 Side: 50 . *&---------------------------------------------------------------------* *& Report ZPROTOTYPE_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zprototype_structural. *----------------------------------------------------------------------* * CLASS prototype DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS prototype DEFINITION ABSTRACT.

PUBLIC SECTION. ENDCLASS. "concreteprototype1 IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concreteprototype2 DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concreteprototype2 DEFINITION INHERITING FROM prototype. METHODS: clone REDEFINITION.0 Side: 51 . ENDCLASS. "clone ENDCLASS. "get_id "prototype IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concreteprototype1 DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concreteprototype1 DEFINITION INHERITING FROM prototype. ENDMETHOD. "concreteprototype2 DEFINITION *----------------------------------------------------------------------* * CLASS concreteprototype2 IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concreteprototype2 IMPLEMENTATION. ENDCLASS. ENDCLASS. "concreteprototype2 IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. METHOD clone. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* Version: 1. METHODS: clone REDEFINITION. "clone ENDCLASS. prototype = me. ENDMETHOD. prototype = me. "concreteprototype1 DEFINITION *----------------------------------------------------------------------* * CLASS concreteprototype1 IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concreteprototype1 IMPLEMENTATION.Project: Design Pattern ENDMETHOD. CLASS-METHODS: main. PUBLIC SECTION. PUBLIC SECTION. METHOD clone.

mainapp=>main( ). Down Casting uses assign operator ?= as it can not be checked before runtine create object p2 exporting id = 'II'.Real World example using System. namespace DoFactory.0 Side: 52 . id = c2->get_id( ). ENDCLASS.RealWorld { // MainApp test application class MainApp { static void Main() Version: 1. c1 ?= p1->clone( ). data: p1 type REF TO concreteprototype1 . "endmethod "mainapp IMPLEMENTATION * * ENDMETHOD.p2 TYPe REF TO concreteprototype2 .c1 type REF TO concreteprototype1 . id = c1->get_id( ). START-OF-SELECTION.Prototype.Collections. // Prototype pattern -. using System.Project: Design Pattern * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. id.GangOfFour. c2 ?= p2->clone( ).1. id. * Create two instances and clone each create object p1 exporting id = 'I'. write: / 'Cloned: {0}'.4. METHOD main. field-SYMBOLS <fs> type REF TO prototype. user-defined Colors of the same type.id type string .7 Sample code In C# This real-world code demonstrates the Prototype pattern in which new Color objects are created by copying pre-existing. write: / 'Cloned: {0}'.c2 type REF TO concreteprototype2 . Output Program ZPROTOTYPE_STRUCTURAL Cloned: {0} I Cloned: {0} II 2.

color = colormanager[name]. this. 34. 0). 20). blue. this.Clone() as Color. // Wait for user Console.0 Side: 53 . 0). name = "peace". colormanager["green"] = new Color( 0. // User uses selected colors string name = "red".Clone() as Color. 255.blue = blue. } // Create a shallow copy public override ColorPrototype Clone() { Version: 1. int green. colormanager["flame"] = new Color(211. } // "ConcretePrototype" class Color : { private int private int private int ColorPrototype red. 0.red = red. 0.Project: Design Pattern { ColorManager colormanager = new ColorManager(). // Constructor public Color(int red. name = "flame".green = green. 211. // Initialize with standard colors colormanager["red" ] = new Color(255.Read(). 54. 255). int blue) { this. color = colormanager[name]. colormanager["peace"] = new Color(128. green. // User adds personalized colors colormanager["angry"] = new Color(255. Color color. 0). 128). color = colormanager[name]. } } // "Prototype" abstract class ColorPrototype { public abstract ColorPrototype Clone(). colormanager["blue" ] = new Color( 0.Clone() as Color.

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.{2. user-defined Colors of the same type.WriteLine( "Cloning color RGB: {0.3}. value). 0 Cloning color RGB: 128. // Indexer public ColorPrototype this[string name] { get { return colors[name] as ColorPrototype. 20 2. 34. In the clone method this example does not create a new instance. red. } } // Prototype manager class ColorManager { Hashtable colors = new Hashtable().211.0 Side: 54 .128 Cloning color RGB: 211.{1. 0. } } } } Output Cloning color RGB: 255. } set { colors. green.8 Sample code In ABAP This real-world code demonstrates the Prototype pattern in which new Color objects are created by copying pre-existing. blue).3}". *&---------------------------------------------------------------------* *& Report ZPROTOTYPE_REALWORLD *& *&---------------------------------------------------------------------* *& Version: 1. but merely returns actual instans and thereby you have two variables pointing to the same instance.Project: Design Pattern Console.MemberwiseClone() as ColorPrototype.4. return this.Add(name.1.3}.

END OF ty_colors. xred = red. METHODS: constructor IMPORTING red TYPE i green TYPE i blue TYPE i .Project: Design Pattern *& *&---------------------------------------------------------------------* REPORT zprototype_realworld. "concreteprototype1 IMPLEMENTATION *----------------------------------------------------------------------* * CLASS colormanager DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS colormanager DEFINITION. "concreteprototype1 DEFINITION *----------------------------------------------------------------------* * CLASS color IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS color IMPLEMENTATION. me->xgreen.3}'. METHODS: clone ABSTRACT RETURNING value(colorprototype) TYPE REF TO colorprototype. PUBLIC SECTION.{2. colorprototype = me.3}.xgreen TYPE i . PUBLIC SECTION. super->constructor( ). xgreen = green. ENDCLASS. "clone ENDCLASS. me->xblue. WRITE: / 'Cloning color RGB: {0.xblue TYPE i. ENDCLASS. PUBLIC SECTION.3}.{1. Version: 1.name TYPE string . xblue = blue. METHOD constructor. ENDMETHOD. TYPES: BEGIN OF ty_colors . ENDMETHOD. DATA: xred TYPE i . PROTECTED SECTION. me->xred. "constructor METHOD clone.clone REDEFINITION. "prototype DEFINITION *----------------------------------------------------------------------* * CLASS color DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS color DEFINITION INHERITING FROM colorprototype. *----------------------------------------------------------------------* * CLASS colorprototype DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS colorprototype DEFINITION ABSTRACT.0 Side: 55 .color TYPE REF TO colorprototype .

ENDCLASS. METHOD get. ENDMETHOD. colormanager->set( EXPORTING name = 'red' pcolor = !color ). FIELD-SYMBOLS <fs> TYPE ty_colors. buffer-name = name. "get method set. METHOD main. * Create the color manager create OBJECT colormanager. "colormanager IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. ENDCLASS. METHODS: get IMPORTING name TYPE string RETURNING value(Pcolors) TYPE REF TO colorprototype .name type string . CLASS-METHODS: main. DATA buffer TYPE ty_colors. READ TABLE me->colors WITH TABLE KEY name = name INTO buffer. endmethod.!color type REF TO color . Version: 1. data: colormanager type REF TO colormanager . colormanager->set( EXPORTING name = 'blue' pcolor = !color ). create OBJECT !color EXPORTING red = 0 green = 0 blue = 255 . buffer-color = pcolor. create OBJECT !color EXPORTING red = 255 green = 0 blue = 0 . "colormanager DEFINITION *----------------------------------------------------------------------* * CLASS colormanager IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS colormanager IMPLEMENTATION. ENDCLASS. INSERT buffer INTO TABLE colors.set IMPORTING name TYPE string pcolor TYPE REF TO colorprototype. DATA buffer TYPE ty_colors. Pcolors = buffer-color.0 Side: 56 . PUBLIC SECTION.Project: Design Pattern DATA: colors TYPE HASHED TABLE OF ty_colors WITH UNIQUE KEY name. create OBJECT !color EXPORTING red = 0 green = 255 blue = 0 . colormanager->set( EXPORTING name = 'green' pcolor = !color ). . "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION.

colormanager->set( EXPORTING name = 'flame' pcolor = !color ). colormanager->set( EXPORTING name = 'peace' pcolor = !color ).{2. !color ?= !color->clone( ). Sometimes it is generalized to systems that operate more efficiently when only one or a few objects exist. START-OF-SELECTION. name = 'red'.3}.3}.{2. name = 'flame'.{1.3}.3}.2 Common Use • Abstract Factory. !color ?= colormanager->get( name ). !color ?= colormanager->get( name ). !color ?= colormanager->get( name ).5. create OBJECT !color EXPORTING red = 211 green = 34 blue = 20 .5. create OBJECT !color EXPORTING red = 128 green = 211 blue = 128 . Version: 1. mainapp=>main( ). name = 'peace'.1 Definition Ensure a class has only one instance and provide a global point of access to it.1. ENDCLASS. This is useful when exactly one object is needed to coordinate actions across the system.3}.3} Cloning color RGB: {0.5 Singleton A class of which only a single instance can exist 2. and Prototype patterns can use Singletons in their implementation. Builder. colormanager->set( EXPORTING name = 'angry' pcolor = !color ). !color ?= !color->clone( ).3}. "!color is a colorprototype "!color is a color "!color is a colorprototype "!color is a color "!color is a colorprototype "!color is a color ENDMETHOD.1.3} Cloning color RGB: {0.{1. It is also considered an anti-pattern since it is often used as a euphemism for global variable. !color ?= !color->clone( ). 2.Project: Design Pattern create OBJECT !color EXPORTING red = 255 green = 54 blue = 0 .0 Side: 57 .1.{2.3} 255 128 211 0 211 34 0 128 20 2. In software engineering. "endmethod "mainapp IMPLEMENTATION Output: Program ZPROTOTYPE_STRUCTURAL Cloning color RGB: {0.{1. the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object.

calls to a singleton e. 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. the constructor is made either private or protected.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.Project: Design Pattern • • • • • Facade objects are often Singletons because only one Facade object is required. Note the distinction between a simple static instance of a class and a singleton: although a singleton can be implemented as a static instance. State objects are often Singletons. if implemented as OOP style the mainapplication class uses local singleton to assure that the program is not run several times. Another notable difference is that static member classes cannot implement an interface. their containing namespace) with unnecessary variables. So if the class has to realize a contract expressed by an interface.0 Side: 58 . o They permit lazy allocation and initialization. Singletons behave differently depending on the lifetime of the virtual machine. requiring no memory or resources until needed. therefore the instance of the singleton remains as well. Singletons are often preferred to global variables because: o They don't pollute the global namespace (or. it can also be lazily constructed.1.g. where global variables in many languages will always consume resources. The singleton pattern must be carefully constructed in multi-threaded applications. Version: 1. To make sure that the object cannot be instantiated any other way. 2. 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. you really have to make it a singleton.5. The classic solution to this problem is to use mutual exclusion on the class that indicates that the object is being instantiated. 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. If two threads are to execute the creation method at the same time when a singleton does not yet exist. in languages with namespaces. within the virtual machine of an application server behave differently. There the virtual machine remains alive. it simply returns a reference to that object. unless that interface is simply a marker. Main application in abap. If an instance already exists.

as the superclass does not know the local class. is if the singleton superclass tries to create instances.Structural example using System.1. 2.4 UML class diagram 2.5. Singleton classes should therefore be marked as FINAL. therefore we are getting type casting problems.0 Side: 59 . // Singleton pattern -.Singleton. as all inheritated classes only have one common instance and because the superclass only have one attribute with the created instance.Project: Design Pattern The singleton are not useful for inheritage. 2.Structural { // MainApp test application class MainApp { static void Main() Version: 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. 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.1. namespace DoFactory. Instance is a class operation responsible for creating and maintaining its own unique instance.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.1. 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.GangOfFour. Another reason for bad inheritance.5.

} return instance.5.Read(). // Note: Constructor is 'protected' protected Singleton() { } public static Singleton Instance() { // Use 'Lazy initialization' if (instance == null) { instance = new Singleton().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.cannot use new Singleton s1 = Singleton. *&---------------------------------------------------------------------* *& Report ZSINGLETON_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& Version: 1. } } // "Singleton" class Singleton { private static Singleton instance.WriteLine("Objects are the same instance").Instance().Project: Design Pattern { // Constructor is protected -. if (s1 == s2) { Console. Singleton s2 = Singleton. } } } Output Objects are the same instance 2. } // Wait for user Console.Instance().0 Side: 60 .1.

cannot use create object s1 = singleton=>instance( ). DATA: s1 TYPE REF TO singleton . ENDCLASS.0 Side: 61 . CLASS-METHODS: main. WRITE: / 'Objects are the same instance'. * Constructor is protected --. METHOD constructor. "singleton IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. CREATE OBJECT x_instance. instance = x_instance. Version: 1. PUBLIC SECTION. "constructor METHOD instance.Project: Design Pattern *&---------------------------------------------------------------------* REPORT zsingleton_structural. IF x_instance IS INITIAL. PUBLIC SECTION. ENDIF. s2 = singleton=>instance( ). IF s1 = s2. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. CLASS-DATA x_instance TYPE REF TO singleton. "instance ENDCLASS. ENDCLASS. ENDMETHOD. *----------------------------------------------------------------------* * CLASS singleton DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS singleton DEFINITION CREATE PRIVATE. METHOD main. ENDIF.s2 TYPE REF TO singleton . ENDMETHOD. "singleton DEFINITION *----------------------------------------------------------------------* * CLASS singleton IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS singleton IMPLEMENTATION. CLASS-METHODS: instance RETURNING value(instance) TYPE REF TO singleton. METHODS: constructor. PRIVATE SECTION.

WriteLine(b1.RealWorld { // MainApp test application class MainApp { static void Main() { LoadBalancer b1 = LoadBalancer b2 = LoadBalancer b3 = LoadBalancer b4 = LoadBalancer. // Same instance? if (b1 == b2 && b2 == b3 && b3 == b4) { Console. ENDCLASS. using System.5.Server).or off-line and every request must go throught the one object that has knowledge about the state of the (web) farm.GetLoadBalancer(). Only a single instance (the singleton) of the class can be created because servers may dynamically come on. mainapp=>main( ).Real World example using System. using System. LoadBalancer. i < 15.Read(). } // All are the same instance -.Project: Design Pattern ENDMETHOD. i++) { Console.Singleton. "endmethod "mainapp IMPLEMENTATION START-OF-SELECTION.8 Sample code In C# This real-world code demonstrates the Singleton pattern as a LoadBalancing object.GangOfFour.Threading.1.Collections. namespace DoFactory.GetLoadBalancer().use b1 arbitrarily // Load balance 15 server requests for (int i = 0.GetLoadBalancer(). LoadBalancer. } } Version: 1. } // Wait for user Console. -----------------------------------Objects are the same instance 2. // Singleton pattern -.GetLoadBalancer().0 Side: 62 .WriteLine("Same instance\n"). LoadBalancer.

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

"server "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 b1 = loadbalancer=>getloadbalancer( b2 = loadbalancer=>getloadbalancer( b3 = loadbalancer=>getloadbalancer( b4 = loadbalancer=>getloadbalancer( use create object ). ). ). ).

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 "mainapp IMPLEMENTATION

ENDMETHOD. ENDCLASS. 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

the adapter makes calls to the instance of the wrapped object. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. if multiple boolean values are stored as a single integer but your consumer requires a 'true'/'false'.This type of adapter uses multiple inheritance to achieve its goal. CLASS lcl_application DEFINITION CREATE PRIVATE. 2. The Class Adapter pattern .2. For instance. ENDCLASS.0 Side: 67 . the adapter would be responsible for extracting the appropriate values from the integer value. 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. In computer programming.1. the Class Adapter pattern cannot be used in languages such as Java that do not support multiple inheritance.2. the adapter contains an instance of the class it wraps. • Version: 1. The adapter is created inheriting interfaces from both the interface that is expected and the interface that is pre-existing. In this situation. Note that when the adapter must adapt multiple adaptees. The default static method should be name RUN() without parameters. 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.In this type of adapter pattern.2 Structural Patterns 2. There are two types of adapter patterns: • The Object Adapter pattern .1 Adapter Match interfaces of different classes 2.Project: Design Pattern as CREATE PRIVATE.1 Definition Convert the interface of a class into another interface clients expect. The adapter is also responsible for handling any logic necessary to transform data into a form that is useful for the consumer.

Project: Design Pattern ObjectAdapter The object adapter pattern expressed in UML. open or show yourself. The adapter hides the adaptee's interface from the client. This tree might have different objects to show. 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. Version: 1. You are also able to let one class use different and several interfaces and thereby accomplish the same effect as in multiple inheritage. Therefore you create a number of interfaces that all the objects involved should be able to respond to e. ClassAdapter The class adapter pattern expressed in UML.2. but support interfaces. Every objects that can be part of the tree implement the interface. 2. 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. With interfaces you are able to use the same interface in different classes.2 Common Use The ABAP language does not support multiple inheritage.g.0 Side: 68 . 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.1.

o Adapter (Compound) o adapts the interface Adaptee to the Target interface.GangOfFour.Structural { // Mainapp test application class MainApp { static void Main() { // Create adapter and place a request Target target = new Adapter(). target. namespace DoFactory.3 UML class diagram 2.4 Participants The classes and/or objects participating in this pattern are: o Target (ChemicalCompound) o defines the domain-specific interface that Client uses.2.1.Structural example using System.Adapter.2.0 Side: 69 . Version: 1.1. These incompatible classes may come from different libraries or frameworks.Request().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. o Client (AdapterApp) o collaborates with objects conforming to the Target interface.Project: Design Pattern 2. // Adapter pattern -. 2.2.1. o Adaptee (ChemicalDatabank) o defines an existing interface that needs adapting.

WriteLine("Called SpecificRequest()"). *&---------------------------------------------------------------------* *& Report ZDP_ADAPTER_STRUCTURAL Version: 1. public override void Request() { // Possibly do some other work // and then call SpecificRequest adaptee.WriteLine("Called Target Request()").Read(). } } } Output Called SpecificRequest() 2. } } // "Adaptee" class Adaptee { public void SpecificRequest() { Console.SpecificRequest().1. } } // "Adapter" class Adapter : Target { private Adaptee adaptee = new Adaptee().2. These incompatible classes may come from different libraries or frameworks.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.0 Side: 70 . } } // "Target" class Target { public virtual void Request() { Console.Project: Design Pattern // Wait for user Console.

CLASS-DATA: adaptee TYPE REF TO adaptee. ENDMETHOD.Project: Design Pattern *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_adapter_structural. "adapter DEFINITION *----------------------------------------------------------------------* Version: 1. METHODS: constructor . PUBLIC SECTION.request REDEFINITION. METHODS: request. PUBLIC SECTION. ENDCLASS. ENDCLASS. "adaptee DEFINITION *----------------------------------------------------------------------* * CLASS adaptee IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS adaptee IMPLEMENTATION. METHOD specificrequest. "specificrequest ENDCLASS. PRIVATE SECTION. WRITE: / 'Called SpecificRequest()'. "request ENDCLASS. "target IMPLEMENTATION *----------------------------------------------------------------------* * CLASS adaptee DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS adaptee DEFINITION. WRITE: / 'Called Target Request()'. "adaptee IMPLEMENTATION *----------------------------------------------------------------------* * CLASS adapter DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS adapter DEFINITION INHERITING FROM target. ENDCLASS. "target DEFINITION *----------------------------------------------------------------------* * CLASS target IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS target IMPLEMENTATION. PUBLIC SECTION. ENDMETHOD.0 Side: 71 . METHODS: specificrequest. METHOD request. *----------------------------------------------------------------------* * CLASS target DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS target DEFINITION.

ENDCLASS. METHOD main. ENDMETHOD.7 Sample code In C# This real-world code demonstrates the use of a legacy chemical databank.0 Side: 72 . METHOD constructor. call METHOD mytarget->request( ).1. CALL METHOD adaptee->specificrequest( ). * Upcasting mytarget = myadapter.2. "request ENDCLASS. CREATE OBJECT adaptee. "adapter IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. CALL METHOD super->constructor. CLASS-METHODS: main. mainapp=>main( ). ENDMETHOD. Chemical compound objects access the databank through an Adapter interface // Adapter pattern -.Project: Design Pattern * CLASS adapter IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS adapter IMPLEMENTATION. PUBLIC SECTION.Real World example Version: 1. "constructor METHOD request. data: mytarget type REF TO target . "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. ENDMETHOD. ENDCLASS. START-OF-SELECTION. * create adapter and place request create OBJECT myadapter.myadapter TYPE REF TO adapter . "endmethod "mainapp IMPLEMENTATION OUTPUT: --------Called SpecificRequest() 2.

0 Side: 73 . protected float meltingPoint. // Adapted chemical compounds Compound water = new RichCompound("Water").Project: Design Pattern using System. // Constructor public Compound(string name) { this. benzene. name). protected double molecularWeight.". Compound benzene = new RichCompound("Benzene").RealWorld { // MainApp test application class MainApp { static void Main() { // Non-adapted chemical compound Compound stuff = new Compound("Unknown"). alcohol. // Wait for user Console.Display().name = name. water.Display().WriteLine("\nCompound: {0} -----. namespace DoFactory. protected string molecularFormula.Display(). } } // "Adapter" class RichCompound : Compound { Version: 1. stuff. Compound alcohol = new RichCompound("Alcohol").Read().Adapter. } } // "Target" class Compound { protected string name.Display(). } public virtual void Display() { Console. protected float boilingPoint.GangOfFour.

Version: 1. break. = 5. molecularWeight). "B"). = -114. string point) { float temperature = 0. break. // Constructor public RichCompound(string name) : base(name) { } public override void Display() { // Adaptee bank = new ChemicalDatabank().WriteLine(" Console.0F.ToLower()) { case "water" : temperature = case "benzene" : temperature case "alcohol" : temperature } } // Boiling Point else { switch (compound.Project: Design Pattern private ChemicalDatabank bank.WriteLine(" Console.GetCriticalPoint(name.0F.GetMolecularWeight(name).WriteLine(" } } // "Adaptee" class ChemicalDatabank { // The Databank 'legacy API' public float GetCriticalPoint(string compound. molecularFormula = bank. meltingPoint). break. molecularWeight = bank. break.Display().ToLower()) { case "water" : temperature = case "benzene" : temperature case "alcohol" : temperature } } return temperature. molecularFormula).3F. Melting Pt: {0}". break.5F. = 80. } Formula: {0}".1F.GetCriticalPoint(name. // Melting Point if (point == "M") { switch (compound. Console.0 Side: 74 . 100. base. = 78. 0. boilingPoint = bank.GetMolecularStructure(name). boilingPoint). "M"). Boiling Pt: {0}".0F.WriteLine(" Console. break. Weight : {0}".1F. meltingPoint = bank.

"benzene" : structure = "C6H6". break. Output Compound: Unknown -----Compound: Water -----Formula: H20 Weight : 18.1 Compound: Alcohol -----Formula: C2H6O2 Weight : 46. } return weight. break.ToLower()) "water" : structure = "H20".1 Boiling Pt: 78.0688 Melting Pt: -114.1134.8 Sample code In ABAP This real-world code demonstrates the use of a legacy chemical databank.ToLower()) { case "water" : weight = 18. "alcohol" : structure = "C2H6O2". break.0.015 Melting Pt: 0 Boiling Pt: 100 Compound: Benzene -----Formula: C6H6 Weight : 78. break.015.5 Boiling Pt: 80. } } } (compound. structure.0 Side: 75 .1134 Melting Pt: 5.Project: Design Pattern public string GetMolecularStructure(string compound) { string structure = "". Chemical compound objects access the databank through an Adapter interface *&---------------------------------------------------------------------* *& Report ZDP_ADAPTER_REALWORLD *& Version: 1. case "benzene" : weight = 78.1.0688. switch { case case case } return } public double GetMolecularWeight(string compound) { double weight = 0. break. case "alcohol" : weight = 46.3 2. break. switch (compound.2.

boilingpoint TYPE _float . me->name = name. DATA: name TYPE _string .getmolecularweight IMPORTING compound TYPE _string RETURNING value(weight) TYPE _double . *----------------------------------------------------------------------* * CLASS compound DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS compound DEFINITION. "display ENDCLASS. TYPES: _float TYPE float ._double TYPE p LENGTH 4 DECIMALS 4 . METHODS: getcriticalpoint IMPORTING compound TYPE _string point TYPE _string RETURNING value(temperature) TYPE _float . "adaptee DEFINITION Version: 1. PROTECTED SECTION. "compound DEFINITION *----------------------------------------------------------------------* * CLASS compound IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS compound IMPLEMENTATION.Project: Design Pattern *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_adapter_zdp_adapter_realworld. /2(30)'Compound: -----'.display.meltingpoint TYPE _float ._string TYPE string. "constructor METHOD display. name . ENDCLASS.0 Side: 76 .molecularformula TYPE _string . "compound IMPLEMENTATION *----------------------------------------------------------------------* * CLASS chemicaldatabank DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS chemicaldatabank DEFINITION. WRITE: /. PUBLIC SECTION.getmolecularstructure IMPORTING compound TYPE _string RETURNING value(structure) TYPE _string . ENDMETHOD. PUBLIC SECTION. METHOD constructor. ENDCLASS. METHODS: constructor IMPORTING name TYPE _string . ENDMETHOD.molecularweight TYPE _double .

"getmolecularweight "adaptee IMPLEMENTATION *----------------------------------------------------------------------* * CLASS Richcompound DEFINITION *----------------------------------------------------------------------* Version: 1. structure = 'H2O'. temperature = '0. ENDCASE. METHOD getcriticalpoint. ENDCASE. WHEN OTHERS. weight = '78. temperature = '5.1'.3'. WHEN 'Benzene'.015'. WHEN 'Benzene'. CASE point.0'. temperature = '100. ENDCASE. WHEN 'Alcohol'. CLEAR structure . temperature = '78. WHEN OTHERS. structure = structure. temperature = temperature. temperature = '-114. CASE compound.1134'. CASE compound. ENDMETHOD.1'. WHEN 'Water'. CASE compound. ENDCLASS. weight = weight. "getmolecularstructure METHOD getmolecularweight.5'. WHEN 'Benzene'. WHEN 'Alcohol'. structure = 'C2H6O2'. CASE compound. "specificrequest METHOD getmolecularstructure. CLEAR temperature . WHEN 'Alcohol'. ENDMETHOD.0688'. WHEN 'Alcohol'. WHEN OTHERS. WHEN 'M'.0 Side: 77 . ENDCASE.0'. ENDMETHOD. WHEN 'Benzene'. temperature = '80. weight = '18. WHEN 'Water'. WHEN OTHERS. ENDCASE. CLEAR weight. WHEN OTHERS.Project: Design Pattern *----------------------------------------------------------------------* * CLASS chemicaldatabank IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS chemicaldatabank IMPLEMENTATION. WHEN 'Water'. WHEN 'Water'. weight = '46. structure = 'C6H6'.

WRITE: /5(30) 'Weight:' . METHODS: constructor IMPORTING name TYPE string . ENDCLASS. DATA: bank TYPE REF TO chemicaldatabank. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. molecularformula.mybenzene TYPE REF TO richcompound . boilingpoint DECIMALS 2 EXPONENT 0. DATA: mystuff TYPE REF TO compound . ENDMETHOD. WRITE: /5(30) 'Boiling Pt:'. molecularformula = bank->getmolecularstructure( me->name ). ENDCLASS. "constructor METHOD display. ENDMETHOD. boilingpoint = bank->getcriticalpoint( compound = me->name point = 'B' ). "Richcompound DEFINITION *----------------------------------------------------------------------* * CLASS Richcompound IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS richcompound IMPLEMENTATION. Version: 1.mywater TYPE REF TO richcompound . ENDCLASS.myalcohol TYPE REF TO richcompound . METHOD constructor. PUBLIC SECTION. CLASS-METHODS: main. METHOD main. WRITE: /5(30) 'Formula:' . CALL METHOD super->display( ). molecularweight = bank->getmolecularweight( me->name ). meltingpoint DECIMALS 2 EXPONENT 0. PRIVATE SECTION. CALL METHOD super->constructor EXPORTING name = name.0 Side: 78 . PUBLIC SECTION. molecularweight . WRITE: /5(30) 'Melting Pt:'.display REDEFINITION.Project: Design Pattern * *----------------------------------------------------------------------* CLASS richcompound DEFINITION INHERITING FROM compound. "request "Richcompound IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. meltingpoint = bank->getcriticalpoint( compound = me->name point = 'M' ). CREATE OBJECT bank.

00 100.Project: Design Pattern * create Richcompound and place request CREATE OBJECT mystuff EXPORTING name = 'Unknown'.0688 -114. it would make sence to ask each element *& what the area was. START-OF-SELECTION. In abap this is best done through interfaces. mywater->display( ).0 Side: 79 . *&---------------------------------------------------------------------* Version: 1.1134 5. OUTPUT: -------"endmethod "mainapp IMPLEMENTATION Compound: Compound: Formula: Weight: Melting Pt: Boiling Pt: Compound: Formula: Weight: Melting Pt: Boiling Pt: Compound: Formula: Weight: Melting Pt: Boiling Pt: Unknown Water H2O 18.10 78. In the example I also uses aliases to make the *& use more simpel from the element implementation. CREATE OBJECT mybenzene EXPORTING name = 'Benzene'. CREATE OBJECT myalcohol EXPORTING name = 'Alcohol'.10 Alcohol C2H6O2 46.00 Benzene C6H6 78. triangle and square.2. ENDMETHOD.50 80. mainapp=>main( ). myalcohol->display( ). triangle and circle and the client want to get the elements area by using the same interface GET_AREA().1. *&---------------------------------------------------------------------* *& Report ZDP_ADAPTER_EKSEMPEL *& *&---------------------------------------------------------------------* *& Exampel of the use of ADAPTER patterns. Here *& we need the interface GET_AREAL() as a commond method for all three *& grafihical elements. In this application we have *& 3 different classes circle. These 3 grafical *& elements obviously have different attributes and behavior. mybenzene->display( ). mystuff->display( ).30 2. But from *& the clients point of view.0150 0. ENDCLASS.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. CREATE OBJECT mywater EXPORTING name = 'Water'.

ALIASES get_areal FOR lif_figur~get_areal. ENDINTERFACE. DATA: laengde TYPE i . pi = 22 / 7. PUBLIC SECTION. ALIASES get_areal FOR lif_figur~get_areal. "constructor METHOD get_areal. DATA: pi TYPE f.Project: Design Pattern REPORT zdp_adapter_eksempel. METHOD constructor. METHODS: constructor IMPORTING l TYPE i b TYPE i. ENDMETHOD. DATA: radius TYPE i. ENDCLASS. METHODS: get_areal RETURNING value(areal) TYPE i. "lcl_cirkel IMPLEMENTATION *----------------------------------------------------------------------* * CLASS lcl_firkant DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_firkant DEFINITION. METHODS: constructor IMPORTING r TYPE i. "lif_figur *----------------------------------------------------------------------* * CLASS lcl_cirkel DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_cirkel DEFINITION.bredde TYPE i. INTERFACES: lif_figur.0 Side: 80 . "lcl_firkant DEFINITION Version: 1. *----------------------------------------------------------------------* * INTERFACE lif_figur *----------------------------------------------------------------------* * *----------------------------------------------------------------------* INTERFACE lif_figur. areal = ( me->radius ** 2 ) * pi. ENDMETHOD. INTERFACES: lif_figur. "get_areal ENDCLASS. me->radius = r. ENDCLASS. PUBLIC SECTION. "lcl_cirkel DEFINITION *----------------------------------------------------------------------* * CLASS lcl_cirkel IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_cirkel IMPLEMENTATION.

ALIASES get_areal FOR lif_figur~get_areal. me->bredde = b. "get_areal ENDCLASS. INTERFACES: lif_figur.Project: Design Pattern *----------------------------------------------------------------------* * CLASS lcl_firkant IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_firkant IMPLEMENTATION. CLASS-METHODS: run. METHODS: constructor. DATA: hojde TYPE i . ENDCLASS. ENDMETHOD. PRIVATE SECTION. METHOD constructor. "constructor METHOD get_areal. "lcl_firkant IMPLEMENTATION *----------------------------------------------------------------------* * CLASS lcl_trekant DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_trekant DEFINITION. "lcl_trekant DEFINITION *----------------------------------------------------------------------* * CLASS lcl_trekant IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_trekant IMPLEMENTATION. Version: 1. PUBLIC SECTION. ENDMETHOD. "get_areal ENDCLASS. ENDMETHOD. "constructor METHOD get_areal. CLASS-DATA: so_application TYPE REF TO lcl_application. me->grundlinie = g. *---------------------------------------------------------CLASS lcl_application DEFINITION CREATE PRIVATE.grundlinie TYPE i. areal = ( me->hojde / 2 ) * me->grundlinie. areal = me->laengde * me->bredde.0 Side: 81 . METHODS: constructor IMPORTING h TYPE i g TYPE i. PUBLIC SECTION. me->laengde = l. METHOD constructor. "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. me->hojde = h. ENDMETHOD.

= 4 b = 5. = 2 g = 4. areal = o_trekant->get_areal( ).areal TYPE i . MESSAGE exc_text TYPE 'I'. areal. WRITE:/ 'Cirklens areal er '. DATA: exc_ref TYPE REF TO cx_root .0 Side: 82 . *---------------------------------------------------------METHOD constructor. * Sa beder vi objekterne om at fortælle deres areal. ENDTRY. * Use the constructor for instantiating internal objects. WRITE:/ 'Trekantens areal er '. areal.o_trekant TYPE REF TO lcl_trekant . areal = o_firkant->get_areal( ). ENDMETHOD. areal. Version: 1. exc_text = exc_ref->get_text( ). IF lcl_application=>so_application IS INITIAL. ENDMETHOD. CATCH cx_sy_create_object_error INTO exc_ref. "run *---------------------------------------------------------* LCL_APPLICATION->CONSTRUCTOR().exc_text TYPE string . ENDIF. DATA: o_cirkel TYPE REF TO lcl_cirkel .o_firkant TYPE REF TO lcl_firkant . io_name TYPE string.Project: Design Pattern DATA: ENDCLASS. "constructor "lcl_application IMPLEMENTATION ENDCLASS. areal = o_cirkel->get_areal( ). TRY. WRITE:/ 'Firkantens areal er '. *---------------------------------------------------------METHOD run. * Først danner vi objekt referencerne CREATE OBJECT o_cirkel EXPORTING r CREATE OBJECT o_trekant EXPORTING h CREATE OBJECT o_firkant EXPORTING l på de enkelte figurer = 24. * fields. tables and events. START-OF-SELECTION. CREATE OBJECT lcl_application=>so_application. *---------------------------------------------------------* LCL_APPLICATION->RUN(). "lcl_application DEFINITION *---------------------------------------------------------* IMPLEMENTATION *---------------------------------------------------------CLASS lcl_application IMPLEMENTATION.

aggregation. Having the shape itself implement them all. each with its own properties.2. they can vary independently. The bridge helps by allowing the creation of new classes that provide the drawing implementation.2 Bridge Separates an object’s interface from its implementation 2.[ Car abstraction Version: 1. If a new shape needs to be created or there is a new graphics API to be drawn on. There are many types of shapes. and can use inheritance to separate responsibilities into different classes. The implementation class. Shapes have to be able to be drawn on many types of systems. or modifying the shape class to work with different architectures is not practical. 2.Project: Design Pattern lcl_application=>run( ).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 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.0 Side: 83 .2. The bridge pattern is useful when not only the class itself varies often but also what the class does. shape.).2. drawing.2. The abstract class. The bridge uses encapsulation. provides an interface for drawing graphics.2 Common Use Shape abstraction When the abstraction and implementation are separated. 2. And there are things that all shapes do. The class itself can be thought of as the abstraction and what the class can do as the implementation. When a class varies often. Consider the abstraction of shapes. One thing all shapes can do is draw themselves.2. However. 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). drawing graphics to a screen can sometimes be dependent on different graphics implementations or operating systems. then it is very easy to add a new class that implements the needed features. provides methods for getting the size or properties of a shape.

Any car refinement needs to be able to drive on any type of road.5 Sample code In C# 2. a Jaguar and a Mercedes (both are Refinements of the Abstraction). there are two types of road.0 Side: 84 .2. Version: 1. The example could be more accurate.2. created by Nvineeth using dpatoolkit 2.3 UML class diagram class diagram of the bridge design pattern.2. Finally. this concept is what the Bridge Pattern is all about. and therefore these methods should not be part of the component butmoved to the composite.Project: Design Pattern Imagine two types of cars (the abstraction).4 Participants 2.3 Composite A tree structure of simple and composite objects 2.1 Definition Compose objects into tree structures to represent part-whole hierarchies.2.2.2. the only common methods are the constructor and display. The road is the Implementor (see image below). A highway and an interstate highway are the Implementation Details.2.3.2. 2. The Abstraction defines that a Car has features such as tires and an engine. Composite lets clients treat individual objects and compositions of objects uniformly. Refinements of the Abstraction declare what specific kind of tires and engine it has. as the leaf can neither remove or add.

(optional) defines an interface for accessing a component's parent in the recursive structure.3.Project: Design Pattern 2. and implements it if that's appropriate.2 UML class diagram 2. defines behavior for primitive objects in the composition. • Client (CompositeApp) o manipulates objects in the composition through the Component interface.3 Participants The classes and/or objects participating in this pattern are: • Component (DrawingElement) o declares the interface for objects in the composition.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. declares an interface for accessing and managing its child components. A leaf has no children. as appropriate. • Composite (CompositeElement) o defines behavior for components having children. implements default behavior for the interface common to all classes. Version: 1. implements child-related operations in the Component interface.0 Side: 85 .3.2. 2.2. • Leaf (PrimitiveElement) o represents leaf objects in the composition. stores child components.2.

// Constructor public Component(string name) { this.Add(new Leaf("Leaf B")).Display(1).Add(new Leaf("Leaf A")). root. comp. } public abstract void Add(Component c).Project: Design Pattern // Composite pattern -. root. // Recursively display tree root.Collections.GangOfFour. root.Add(leaf). // Wait for user Console.0 Side: 86 .Remove(leaf).Add(new Leaf("Leaf XA")). Composite comp = new Composite("Composite X"). namespace DoFactory. root. using System.Add(new Leaf("Leaf XB")).Structural example using System. public abstract void Display(int depth). } Version: 1. } } // "Component" abstract class Component { protected string name.Add(new Leaf("Leaf C")).name = name. comp. root. root. // Add and remove a leaf Leaf leaf = new Leaf("Leaf D").Add(comp).Composite.Read(). public abstract void Remove(Component c).Structural { // MainApp test application class MainApp { static void Main() { // Create a tree structure Composite root = new Composite("root").

Add(component). } public override void Display(int depth) { Console. } } } // "Leaf" class Leaf : Component { // Constructor public Leaf(string name) : base(name) { } public override void Add(Component c) { Console. } Version: 1.WriteLine(new String('-'.WriteLine("Cannot remove from a leaf"). } public override void Display(int depth) { Console.Project: Design Pattern // "Composite" class Composite : Component { private ArrayList children = new ArrayList().Display(depth + 2). // Constructor public Composite(string name) : base(name) { } public override void Add(Component component) { children. } public override void Remove(Component c) { Console.WriteLine(new String('-'. } public override void Remove(Component component) { children.WriteLine("Cannot add to a leaf"). depth) + name). // Recursively display child nodes foreach (Component component in children) { component.Remove(component). depth) + name).0 Side: 87 .

3. *----------------------------------------------------------------------* * CLASS component DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS component DEFINITION ABSTRACT. *&---------------------------------------------------------------------* *& Report ZDP_COMPOSITE_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_composite_structural. ENDCLASS.remove ABSTRACT IMPORTING component TYPE REF TO component .Project: Design Pattern } } Output -root ---Leaf A ---Leaf B ---Composite X -----Leaf XA -----Leaf XB ---Leaf C 2. METHOD constructor.0 Side: 88 . "constructor ENDCLASS. PUBLIC SECTION. "component IMPLEMENTATION *----------------------------------------------------------------------* * CLASS composite DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS composite DEFINITION INHERITING FROM component. DATA: name TYPE string.add ABSTRACT IMPORTING component TYPE REF TO component .2.display ABSTRACT IMPORTING depth TYPE i . PROTECTED SECTION. "component DEFINITION *----------------------------------------------------------------------* * CLASS component IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS component IMPLEMENTATION. Version: 1. me->name = name.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. METHODS: constructor IMPORTING name TYPE string . PUBLIC SECTION. ENDMETHOD.

ENDMETHOD. PRIVATE SECTION. Version: 1.0 Side: 89 . FIELD-SYMBOLS <fs> TYPE REF TO component. DATA mydepth TYPE i. IF <fs> = component. "composite IMPLEMENTATION *----------------------------------------------------------------------* * CLASS leaf DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS leaf DEFINITION INHERITING FROM component. mydepth = depth + 1.remove REDEFINITION . LOOP AT children ASSIGNING <fs>. METHOD add. ENDMETHOD. "remove METHOD display. <fs>->display( EXPORTING depth = mydepth ). write '-'. ENDMETHOD. LOOP AT children ASSIGNING <fs>. index = sy-tabix. DATA children TYPE TABLE OF REF TO component. PUBLIC SECTION. ENDCLASS. ENDLOOP. data: index type sy-tabix. ENDIF. "add METHOD remove. DELETE children INDEX index. ENDIF. do depth times. IF sy-subrc = 0. ENDMETHOD. "composite DEFINITION *----------------------------------------------------------------------* * CLASS composite IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS composite IMPLEMENTATION.Project: Design Pattern METHODS: add REDEFINITION . write: /. FIELD-SYMBOLS <fs> TYPE REF TO component. "display METHOD new. WRITE: me->name. CREATE OBJECT composite EXPORTING name = name. CLASS-METHODS: new IMPORTING name TYPE string RETURNING value(composite) TYPE REF TO composite . ENDLOOP. INSERT component INTO TABLE children. "new ENDCLASS. enddo.display REDEFINITION . EXIT.

enddo. ENDMETHOD. myleaf = leaf=>new('Leaf C'). ENDMETHOD. "remove METHOD display. "leaf IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. "display METHOD new.display REDEFINITION . write: /. myroot->add( myleaf ). myroot->add( myleaf ). DATA: myroot TYPE REF TO composite . METHOD add. PUBLIC SECTION. "add METHOD remove. write '-'. "leaf DEFINITION *----------------------------------------------------------------------* * CLASS leaf IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS leaf IMPLEMENTATION. mycomposite->add( myleaf ). myroot = composite=>new('root'). do depth times. ENDCLASS. ENDMETHOD. myleaf = leaf=>new('Leaf A').Project: Design Pattern METHODS: add REDEFINITION .mycomposite TYPE REF TO composite . WRITE: / 'Cannot add to a leaf'. myroot->add( mycomposite ).0 Side: 90 myroot->add( myleaf ). Version: 1. "new ENDCLASS. myleaf = leaf=>new('Leaf XB'). WRITE: / 'Cannot remove from a leaf'.remove REDEFINITION . myleaf = leaf=>new('Leaf XA'). ENDMETHOD.myleaf TYPE REF TO leaf . . METHOD main. CREATE OBJECT leaf EXPORTING name = name. WRITE: me->name. mycomposite = composite=>new('Composite X'). mycomposite->add( myleaf ). CLASS-METHODS: main. CLASS-METHODS: new IMPORTING name TYPE string RETURNING value(leaf) TYPE REF TO leaf . myleaf = leaf=>new('Leaf B'). ENDCLASS. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION.

using System. CompositeElement comp = new CompositeElement("Two Circles"). // Add and remove a PrimitiveElement PrimitiveElement pe = new PrimitiveElement("Yellow Line"). root.Add(pe).Leaf XA . myroot->remove( myleaf )...RealWorld { // Mainapp test application class MainApp { static void Main() { // Create a tree structure CompositeElement root = new CompositeElement("Picture"). root.Leaf C myroot->add( myleaf ).Remove(pe).Add(new PrimitiveElement("Blue Circle")).Add(new PrimitiveElement("Green Box")). etc) and composite nodes (groups of drawing elements that make up more complex elements).Composite X ..Leaf XB .. root. root...Leaf B ..Add(new PrimitiveElement("White Circle")). comp.Project: Design Pattern myleaf = leaf=>new('Leaf D').GangOfFour. ENDCLASS. mainapp=>main( ). circles.Add(new PrimitiveElement("Red Line")).Add(new PrimitiveElement("Black Circle")).root . root. "endmethod "mainapp IMPLEMENTATION 2.Leaf A . using System. START-OF-SELECTION. OUTPUT: . comp.2. namespace DoFactory. myroot->display( 1 ). ENDMETHOD. root.Composite.Collections.3.Add(comp). // Recursively display nodes Version: 1..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.0 Side: 91 .

WriteLine( "Cannot remove from a PrimitiveElement"). } // "Leaf" class PrimitiveElement : DrawingElement { // Constructor public PrimitiveElement(string name) : base(name) { } public override void Add(DrawingElement c) { Console.Read(). public abstract void Display(int indent).Display(1).0 Side: 92 . public abstract void Remove(DrawingElement d). Version: 1. } public override void Display(int indent) { Console.WriteLine( new String('-'. // Constructor public DrawingElement(string name) { this.Project: Design Pattern root. // Constructor public CompositeElement(string name) : base(name) { } public override void Add(DrawingElement d) { elements. } } // "Composite" class CompositeElement : DrawingElement { private ArrayList elements = new ArrayList().name = name. } public override void Remove(DrawingElement c) { Console. } public abstract void Add(DrawingElement d). } } // "Component" Treenode abstract class DrawingElement { protected string name.Add(d). // Wait for user Console. indent) + " " + name).WriteLine( "Cannot add to a PrimitiveElement").

indent) + "+ " + name).Black Circle ----. etc) and composite nodes (groups of drawing elements that make up more complex elements).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.Remove(d).2. PUBLIC SECTION.display ABSTRACT IMPORTING indent TYPE i . PROTECTED SECTION. Version: 1. *&---------------------------------------------------------------------* *& Report ZDP_COMPOSITE_REALWORLD *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_composite_realworld.White Circle 2. *----------------------------------------------------------------------* * CLASS DrawingElement DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS drawingelement DEFINITION ABSTRACT. METHODS: constructor IMPORTING name TYPE string .Project: Design Pattern } public override void Remove(DrawingElement d) { elements. } public override void Display(int indent) { Console.add ABSTRACT IMPORTING drawingelement TYPE REF TO drawingelement .Display(indent + 2).Red Line --.remove ABSTRACT IMPORTING drawingelement TYPE REF TO drawingelement . } } } } Output -+ Picture --.Blue Circle --.WriteLine(new String('-'.3. circles. // Display each child element on this node foreach (DrawingElement c in elements) { c.Green Box ---+ Two Circles ----.0 Side: 93 .

index = sy-tabix. DATA myindent TYPE i. IF sy-subrc = 0. ENDIF. METHOD constructor. DATA: index TYPE sy-tabix. EXIT. FIELD-SYMBOLS <fs> TYPE REF TO drawingelement. ENDMETHOD. IF <fs> = drawingelement. ENDMETHOD.remove REDEFINITION . ENDDO.0 Side: 94 . METHODS: add REDEFINITION . ENDCLASS. PUBLIC SECTION. ENDMETHOD.display REDEFINITION . Version: 1. ENDIF. me->name = name. "remove METHOD display. INSERT drawingelement INTO TABLE elements. "DrawingElement DEFINITION *----------------------------------------------------------------------* * CLASS DrawingElement IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS drawingelement IMPLEMENTATION.Project: Design Pattern DATA: name TYPE string. "constructor ENDCLASS. DO indent TIMES. DATA elements TYPE TABLE OF REF TO drawingelement. METHOD add. PRIVATE SECTION. LOOP AT elements ASSIGNING <fs>. ENDLOOP. FIELD-SYMBOLS <fs> TYPE REF TO drawingelement. "DrawingElement IMPLEMENTATION *----------------------------------------------------------------------* * CLASS compositeElement DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS compositeelement DEFINITION INHERITING FROM drawingelement. DELETE elements INDEX index. WRITE '-'. "compositeElement DEFINITION *----------------------------------------------------------------------* * CLASS compositeElement IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS compositeelement IMPLEMENTATION. WRITE: /. CLASS-METHODS: new IMPORTING name TYPE string RETURNING value(compositeelement) TYPE REF TO compositeelement . ENDCLASS. "add METHOD remove.

WRITE: me->name.display REDEFINITION . WRITE: /. "add METHOD remove. "display METHOD new. LOOP AT elements ASSIGNING <fs>. CREATE OBJECT compositeelement EXPORTING name = name. PUBLIC SECTION. METHOD add. <fs>->display( EXPORTING indent = myindent ). me->name. ENDCLASS. ENDMETHOD. ENDCLASS. ENDMETHOD. CREATE OBJECT primitiveelement EXPORTING name = name. ENDMETHOD. DO indent TIMES. "PrimitiveElement DEFINITION *----------------------------------------------------------------------* * CLASS PrimitiveElement IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS primitiveelement IMPLEMENTATION. WRITE: / 'Cannot remove from a PrimitiveElement'. METHODS: add REDEFINITION . "new ENDCLASS. CLASS-METHODS: main. CLASS-METHODS: new IMPORTING name TYPE string RETURNING value(primitiveelement) TYPE REF TO primitiveelement .Project: Design Pattern WRITE: '+' . WRITE '-'. "compositeElement IMPLEMENTATION *----------------------------------------------------------------------* * CLASS PrimitiveElement DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS primitiveelement DEFINITION INHERITING FROM drawingelement. "new ENDCLASS. PUBLIC SECTION. ENDMETHOD. myindent = indent + 2. WRITE: / 'Cannot add to a PrimitiveElement'. ENDMETHOD.0 Side: 95 . ENDMETHOD. "PrimitiveElement IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. "remove METHOD display. "mainapp DEFINITION Version: 1. "display METHOD new. ENDLOOP. ENDDO.remove REDEFINITION .

myprimitiveelement TYPE REF TO primitiveelement . Decorators provide a flexible alternative to subclassing for extending functionality. START-OF-SELECTION. myroot->display( 1 ). mycompositeelement = compositeelement=>new('Two Circles').. myroot->add( myprimitiveelement ). myroot->add( mycompositeelement ). myroot->add( myprimitiveelement ).Blue Circle . myprimitiveelement = primitiveelement=>new('Black Circle'). mycompositeelement->add( myprimitiveelement ). myprimitiveelement = primitiveelement=>new('Gree Box').+ Two Circles . myprimitiveelement = primitiveelement=>new('White Circle'). myprimitiveelement = primitiveelement=>new('Red Line').mycompositeelement TYPE REF TO compositeelement .2.. myroot->remove( myprimitiveelement ). myroot->add( myprimitiveelement ). myprimitiveelement = primitiveelement=>new('Blue Circle'). mainapp=>main( ).2..White Circle "endmethod "mainapp IMPLEMENTATION myroot->add( 2.4.Project: Design Pattern *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. METHOD main. myprimitiveelement = primitiveelement=>new('Yellow Line'). OUTPUT: + Picture . ENDMETHOD. mycompositeelement->add( myprimitiveelement ).0 Side: 96 . Version: 1.Gree Box . myprimitiveelement ).1 Definition Attach additional responsibilities to an object dynamically.Black Circle . ENDCLASS. DATA: myroot TYPE REF TO compositeelement . myroot = compositeelement=>new('Picture')..Red Line .4 Decorator Add responsibilities to objects dynamically 2.

// Decorator pattern -. ConcreteDecorator (Borrowable) o adds responsibilities to the component.4.2. namespace DoFactory.4.Structural example using System.2 UML class diagram 2. Video) o defines an object to which additional responsibilities can be attached.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.4 Sample code In C# This structural code demonstrates the Decorator pattern which dynamically adds extra functionality to an existing object. ConcreteComponent (Book.0 Side: 97 .Structural { Version: 1.2.4.Decorator.GangOfFour. Decorator (Decorator) o maintains a reference to a Component object and defines an interface that conforms to Component's interface. • 2.Project: Design Pattern 2.2.

Operation(). } public override void Operation() { if (component != null) { component.component = component. // Wait for user Console. } // "ConcreteComponent" class ConcreteComponent : Component { public override void Operation() { Console.SetComponent(c). d2. } } // "Component" abstract class Component { public abstract void Operation().Operation()").WriteLine("ConcreteComponent. } Version: 1. ConcreteDecoratorB d2 = new ConcreteDecoratorB().0 Side: 98 .Operation(). ConcreteDecoratorA d1 = new ConcreteDecoratorA(). d2.Project: Design Pattern // MainApp test application class MainApp { static void Main() { // Create ConcreteComponent and two Decorators ConcreteComponent c = new ConcreteComponent(). } } // "Decorator" abstract class Decorator : Component { protected Component component.Read(). // Link decorators d1. public void SetComponent(Component component) { this.SetComponent(d1).

Operation() 2. Console.Operation() ConcreteDecoratorA. } void AddedBehavior() { } } } Output ConcreteComponent.Operation() ConcreteDecoratorB.Project: Design Pattern } } // "ConcreteDecoratorA" class ConcreteDecoratorA : Decorator { private string addedState. *----------------------------------------------------------------------* * CLASS component DEFINITION *----------------------------------------------------------------------* Version: 1.0 Side: 99 .Operation(). *&---------------------------------------------------------------------* *& Report ZDP_DECORATOR_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_decorator_structural.2.WriteLine("ConcreteDecoratorB. public override void Operation() { base. Console.Operation().5 Sample code In ABAP This structural code demonstrates the Decorator pattern which dynamically adds extra functionality to an existing object.WriteLine("ConcreteDecoratorA.Operation()").Operation()"). AddedBehavior(). } } // "ConcreteDecoratorB" class ConcreteDecoratorB : Decorator { public override void Operation() { base.4. addedState = "New State".

Version: 1. "setcomponent METHOD operation.Operation()'. ENDMETHOD. IF NOT component IS INITIAL. ENDIF.0 Side: 100 . me->component = component. DATA: component TYPE REF TO component. "decorator IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concretedecoratora DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretedecoratora DEFINITION INHERITING FROM decorator. "component DEFINITION *----------------------------------------------------------------------* * CLASS concretecomponent DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretecomponent DEFINITION INHERITING FROM component. PROTECTED SECTION. PUBLIC SECTION. PUBLIC SECTION. METHODS: operation REDEFINITION. "operation ENDCLASS. METHODS: setcomponent IMPORTING component TYPE REF TO component .Project: Design Pattern * *----------------------------------------------------------------------* CLASS component DEFINITION ABSTRACT. METHOD operation. WRITE: / 'ConcreteComponent. ENDCLASS. ENDMETHOD. ENDMETHOD. ENDCLASS. ENDCLASS. METHOD setcomponent. component->operation( ). "concretecomponent DEFINITION *----------------------------------------------------------------------* * CLASS concretecomponent IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretecomponent IMPLEMENTATION. METHODS: operation ABSTRACT. PUBLIC SECTION. "operation ENDCLASS. "decorator DEFINITION *----------------------------------------------------------------------* * CLASS decorator IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS decorator IMPLEMENTATION.operation REDEFINITION . "concretecomponent IMPLEMENTATION *----------------------------------------------------------------------* * CLASS decorator DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS decorator DEFINITION INHERITING FROM component ABSTRACT.

"concretedecoratora IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concretedecoratorb DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretedecoratorb DEFINITION INHERITING FROM decorator. DATA: addedstate TYPE string. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. ENDCLASS. METHODS: operation REDEFINITION. ENDMETHOD. DATA: c TYPE REF TO concretecomponent . METHOD operation. "concretedecoratora DEFINITION *----------------------------------------------------------------------* * CLASS concretedecoratora IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretedecoratora IMPLEMENTATION. PUBLIC SECTION. CLASS-METHODS: main. ENDMETHOD.Operation()'.d1 TYPE REF TO concretedecoratora Version: 1. PRIVATE SECTION. WRITE: / 'ConcreteDecoratorA. super->operation( ). me->addedbehavior( ). PUBLIC SECTION.Project: Design Pattern PUBLIC SECTION.0 Side: 101 . ENDCLASS. addedstate = 'New State'. "addedbehavior ENDCLASS. WRITE: / 'ConcreteDecoratorB. METHODS: operation REDEFINITION . "operation METHOD addedbehavior. ENDCLASS. "concretedecoratorb IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION.addedbehavior . METHOD main. super->operation( ). "concretedecoratorb DEFINITION *----------------------------------------------------------------------* * CLASS concretedecoratorb IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretedecoratorb IMPLEMENTATION. METHOD operation. "operation ENDCLASS.Operation()'. ENDMETHOD.

Display(). using System. // Decorator pattern -. d2->operation( ).Decorator.Real World example using System. d1->setcomponent( c ).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). OUTPUT: --------------------ConcreteComponent. borrowvideo.4.RealWorld { // MainApp test application class MainApp { static void Main() { // Create book Book book = new Book ("Worley". mainapp=>main( ). borrowvideo.2. 23. 10). video. ENDMETHOD.Project: Design Pattern .0 Side: 102 .NET". book. Borrowable borrowvideo = new Borrowable(video).Display(). d1.d2 TYPE .Operation() ConcreteDecoratorA.GangOfFour.BorrowItem("Customer #1"). START-OF-SELECTION. ENDCLASS. "Jaws". borrowvideo. "Inside ASP. CREATE OBJECT CREATE OBJECT CREATE OBJECT REF TO concretedecoratorb c. d2->setcomponent( d1 ).Display(). then borrow and display Console.Operation() ConcreteDecoratorB.Operation() "endmethod "mainapp IMPLEMENTATION 2. 92). Version: 1.Collections.BorrowItem("Customer #2"). // Make video borrowable.WriteLine("\nMaking video borrowable:"). // Create video Video video = new Video ("Spielberg". namespace DoFactory. d2.

Read(). Console. private string title. NumCopies). private int playTime.title = title."). Console. // Property public int NumCopies { get{ return numCopies. private string title. // Constructor public Video(string director. } set{ numCopies = value.author = author. } } public abstract void Display().Project: Design Pattern // Wait for user Console. } public override void Display() { Console. string title.WriteLine(" # Copies: {0}".WriteLine(" Author: {0}".WriteLine("\nBook -----.WriteLine(" Title: {0}". this.NumCopies = numCopies. title). Version: 1. Console.string title. } } // "Component" abstract class LibraryItem { private int numCopies. author). // Constructor public Book(string author. } // "ConcreteComponent" class Book : LibraryItem { private string author.int numCopies) { this.0 Side: 103 . this. } } // "ConcreteComponent" class Video : LibraryItem { private string director.

WriteLine(" Playtime: {0}\n". } public void ReturnItem(string name) { Version: 1. title).playTime = playTime.0 Side: 104 . Console. director). } public override void Display() { libraryItem. Console.Add(name). } public override void Display() { Console. Console.Project: Design Pattern int numCopies. } } // "Decorator" abstract class Decorator : LibraryItem { protected LibraryItem libraryItem. playTime). this.NumCopies = numCopies. // Constructor public Decorator(LibraryItem libraryItem) { this. this. int playTime) { this. this.WriteLine(" # Copies: {0}".WriteLine(" Director: {0}".libraryItem = libraryItem.WriteLine(" Title: {0}". libraryItem. // Constructor public Borrowable(LibraryItem libraryItem) : base(libraryItem) { } public void BorrowItem(string name) { borrowers.director = director.Display(). NumCopies).WriteLine("\nVideo ----.title = title.").NumCopies--. } } // "ConcreteDecorator" class Borrowable : Decorator { protected ArrayList borrowers = new ArrayList(). Console.

Project: Design Pattern borrowers.4. *&---------------------------------------------------------------------* *& Report ZDP_DECORATOR_REALWORLD *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_decorator_realworld.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).2. *----------------------------------------------------------------------* * CLASS property DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* Version: 1.0 Side: 105 . } } } } Output Book -----Author: Worley Title: Inside ASP. libraryItem.NumCopies++.Display(). foreach (string borrower in borrowers) { Console.WriteLine(" borrower: " + borrower).Remove(name).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. } public override void Display() { base.

me->value = value.display REDEFINITION.Project: Design Pattern CLASS property DEFINITION. METHODS: get RETURNING value(value) TYPE i . "constructor ENDCLASS. ENDMETHOD. METHOD constructor. DATA: author TYPE string . PUBLIC SECTION. "property DEFINITION *----------------------------------------------------------------------* * CLASS property IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS property IMPLEMENTATION. "LibraryItem DEFINITION *----------------------------------------------------------------------* * CLASS libraryitem IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS libraryitem IMPLEMENTATION. DATA: value TYPE i. "property IMPLEMENTATION *----------------------------------------------------------------------* * CLASS LibraryItem DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS libraryitem DEFINITION ABSTRACT. METHOD get. me->numcopies->set( numcopies ). METHODS: constructor IMPORTING author TYPE string title TYPE string numcopies TYPE i . "libraryitem IMPLEMENTATION *----------------------------------------------------------------------* * CLASS book DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS book DEFINITION INHERITING FROM libraryitem. ENDMETHOD. CREATE OBJECT me->numcopies. PUBLIC SECTION.title TYPE string Version: 1. DATA: numcopies TYPE REF TO property. "get METHOD set. "set ENDCLASS. ENDMETHOD.0 Side: 106 .set IMPORTING value TYPE i . PROTECTED SECTION.display ABSTRACT. METHODS: constructor IMPORTING numcopies TYPE i . PUBLIC SECTION. value = me->value. ENDCLASS. PRIVATE SECTION. ENDCLASS.

. numofcopies = me->numcopies->get( )..'. super->constructor( numcopies ). METHOD constructor.. "constructor METHOD display.. WRITE: /5(15)'Director:.. me->playtime = playtime. ENDMETHOD. "display ENDCLASS. PRIVATE SECTION. DATA: numofcopies TYPE i... me->title = title.' ... "constructor METHOD display.'. WRITE: /5(15)'Title:. ENDMETHOD. /2(20)'Video --------------'. numofcopies = me->numcopies->get( ).. WRITE: /. "video DEFINITION *----------------------------------------------------------------------* * CLASS video IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS video IMPLEMENTATION.Project: Design Pattern .. DATA: numofcopies TYPE i. WRITE: /5(15)'# copies:. WRITE: /5(15)'Title:. super->constructor( numcopies ). ENDCLASS.title TYPE string ..... PUBLIC SECTION. "book IMPLEMENTATION *----------------------------------------------------------------------* * CLASS video DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS video DEFINITION INHERITING FROM libraryitem.. me->author = author.. author.. WRITE: /5(15)'Author:. title. title..'. me->title = title..... DATA: director TYPE string . METHOD constructor.display REDEFINITION. me->director = director.. WRITE: /.. /2(20)'Book ---------------'. ENDCLASS.playtime TYPE i . director. METHODS: constructor IMPORTING director TYPE string title TYPE string numcopies TYPE i playtime TYPE i .... "book DEFINITION *----------------------------------------------------------------------* * CLASS book IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS book IMPLEMENTATION. Version: 1..'.. numofcopies .0 Side: 107 . ENDMETHOD....

"decorator IMPLEMENTATION *----------------------------------------------------------------------* * CLASS borrowable DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS borrowable DEFINITION INHERITING FROM decorator. PUBLIC SECTION. "display ENDCLASS. ENDMETHOD.. DATA borrowers TYPE TABLE OF string.returnitem IMPORTING name TYPE string . "constructor METHOD display. METHODS: borrowitem IMPORTING name TYPE string . DATA: libraryitem TYPE REF TO libraryitem. "video IMPLEMENTATION *----------------------------------------------------------------------* * CLASS decorator DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS decorator DEFINITION INHERITING FROM libraryitem ABSTRACT. playtime... ENDCLASS.... METHOD constructor..display REDEFINITION .' .'. WRITE:/5(15)'Playtime:. "display ENDCLASS. ENDMETHOD.0 Side: 108 .Project: Design Pattern WRITE: /5(15)'# copies:. me->libraryitem = libraryitem. ENDMETHOD.. super->constructor( 1 ). METHODS: constructor IMPORTING libraryitem TYPE REF TO libraryitem . DATA: numofcopies TYPE i. "borrowable DEFINITION *----------------------------------------------------------------------* * CLASS borrowable IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS borrowable IMPLEMENTATION. ENDCLASS. PROTECTED SECTION. PROTECTED SECTION. Version: 1.. INSERT name INTO TABLE borrowers. "decorator DEFINITION *----------------------------------------------------------------------* * CLASS decorator IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS decorator IMPLEMENTATION... me->libraryitem->display( ). METHOD borrowitem.display REDEFINITION . PUBLIC SECTION. numofcopies .

LOOP AT borrowers INTO name. "borrowitem METHOD returnitem. me->libraryitem->numcopies->set( numofcopies ). "display ENDCLASS.'. SUBTRACT 1 FROM numofcopies. name. borrowvideo->borrowitem( 'Customer #2' ). / 'Making Vide borrowable'. borrowvideo->display( ). CREATE OBJECT book EXPORTING author = 'Worley' title = 'Inside ASP.Project: Design Pattern numofcopies = me->libraryitem->numcopies->get( ). mainapp=>main( ).borrowvideo TYPE REF TO borrowable . METHOD main.0 Side: 109 . borrowvideo->borrowitem( 'Customer #1' ). WRITE: /. START-OF-SELECTION.video TYPE REF TO video . make video borrowable. CREATE OBJECT video EXPORTING director title numcopies playtime video->display( ). "returnitem super->display( ). book->display( ). * = = = = 'Spielberg' 'Jaws' 23 92. PUBLIC SECTION. CLASS-METHODS: main. ENDCLASS. DATA name TYPE string. "endmethod "mainapp IMPLEMENTATION ENDMETHOD. ENDMETHOD. ENDMETHOD.NET' numcopies = 10. DATA: book TYPE REF TO book . ENDMETHOD. ENDLOOP. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. ENDCLASS. "borrowable IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. WRITE: /10(10)'Borrower:. CREATE OBJECT borrowvideo EXPORTING libraryitem = video. Version: 1. METHOD display. then borrow and display WRITE: /.

.... 2....0 Side: 110 .. Spielberg Title:......... Customer #1 Borrower:...3 Participants The classes and/or objects participating in this pattern are: Version: 1...1 Definition Provide a unified interface to a set of interfaces in a subsystem. Spielberg Title:..Project: Design Pattern OUTPUT: ------Book Author:..5 Facade A single class that represents an entire subsystem 2... Worley Title:.. 92 Borrower:..........2. Customer #2 2..2 UML class diagram 2.... Jaws # copies:.. Façade defines a higher-level interface that makes the subsystem easier to use...2.. 92 Making Vide borrowable Video Director:.......5.5. Inside ASP. 23 Playtime:......2..... Jaws # copies:.5..2.... 21 Playtime:.... 10 Video Director:...NET # copies:.

} } // Subsystem ClassB" class SubSystemTwo { public void MethodTwo() { Console.WriteLine(" SubSystemOne Method").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. have no knowledge of the facade and keep no reference to it. } } // "Subsystem ClassA" class SubSystemOne { public void MethodOne() { Console.Facade. // Facade pattern -. handle work assigned by the Facade object. } Version: 1.2. facade. facade.MethodA(). 2.Structural { // Mainapp test application class MainApp { public static void Main() { Facade facade = new Facade().GangOfFour. delegates client requests to appropriate subsystem objects.Structural example using System. // Wait for user Console.WriteLine(" SubSystemTwo Method"). Credit.5.MethodB(). namespace DoFactory.0 Side: 111 .Read(). Subsystem classes (Bank. Loan) o implement subsystem functionality.Project: Design Pattern • • Facade (MortgageApplication) o knows which subsystem classes are responsible for a request.

three = new SubSystemThree().MethodOne(). two. SubSystemTwo two. } public void MethodA() { Console.MethodTwo().MethodFour(). public Facade() { one = new SubSystemOne(). SubSystemFour four. } public void MethodB() { Console.WriteLine(" SubSystemThree Method").WriteLine("\nMethodA() ---. two = new SubSystemTwo().MethodTwo().WriteLine(" SubSystemFour Method").Project: Design Pattern } // Subsystem ClassC" class SubSystemThree { public void MethodThree() { Console.").WriteLine("\nMethodB() ---. two. four. four = new SubSystemFour(). three. } } } Version: 1. one.MethodThree()."). } } // Subsystem ClassD" class SubSystemFour { public void MethodFour() { Console.0 Side: 112 . SubSystemThree three. } } // "Facade" class Facade { SubSystemOne one.

5. PUBLIC SECTION. *&---------------------------------------------------------------------* *& Report ZDP_FACADE_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_facade_structural. "subsystemone IMPLEMENTATION *----------------------------------------------------------------------* * CLASS subsystemtwo DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subsystemtwo DEFINITION.Project: Design Pattern Output MethodA() ---SubSystemOne Method SubSystemTwo Method SubSystemFour Method MethodB() ---SubSystemTwo Method SubSystemThree Method 2. METHOD methodone.0 Side: 113 . WRITE: / 'SubsystemOne Method'. "methodone ENDCLASS. METHODS: methodone. PUBLIC SECTION. ENDCLASS. "subsystemone DEFINITION *----------------------------------------------------------------------* * CLASS subsystemone IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subsystemone IMPLEMENTATION.2. ENDMETHOD. *----------------------------------------------------------------------* * CLASS subsystemone DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subsystemone DEFINITION. ENDCLASS. "subsystemtwo DEFINITION *----------------------------------------------------------------------* * CLASS subsystemtwo IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* Version: 1.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. METHODS: methodtwo.

WRITE: / 'SubsystemThree Method'. "subsystemThree DEFINITION *----------------------------------------------------------------------* * CLASS subsystemthree IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subsystemthree IMPLEMENTATION. METHOD methodfour. "subsystemthree IMPLEMENTATION *----------------------------------------------------------------------* * CLASS subsystemfour DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subsystemfour DEFINITION. METHOD methodthree.three TYPE REF TO subsystemthree . WRITE: / 'SubsystemTwo Method'. WRITE: / 'SubsystemFour Method'. "subsystemfour IMPLEMENTATION *----------------------------------------------------------------------* * CLASS facade DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS facade DEFINITION. ENDMETHOD. ENDMETHOD. METHOD methodtwo. ENDCLASS.methoda Version: 1. PUBLIC SECTION.two TYPE REF TO subsystemtwo . "methodthree ENDCLASS. METHODS: constructor . "subsystemtwo IMPLEMENTATION *----------------------------------------------------------------------* * CLASS subsystemThree DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subsystemthree DEFINITION.four TYPE REF TO subsystemfour . "methodfour ENDCLASS. DATA: one TYPE REF TO subsystemone . ENDMETHOD. PUBLIC SECTION. "subsystemfour DEFINITION *----------------------------------------------------------------------* * CLASS subsystemfour IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subsystemfour IMPLEMENTATION. "methodtwo ENDCLASS. METHODS: methodfour. METHODS: methodthree. ENDCLASS.0 Side: 114 .Project: Design Pattern CLASS subsystemtwo IMPLEMENTATION. PUBLIC SECTION.

"facade DEFINITION *----------------------------------------------------------------------* * CLASS facade IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS facade IMPLEMENTATION. CREATE OBJECT one. one->methodone( ). METHOD constructor. ENDMETHOD. CREATE OBJECT facade. DATA: facade TYPE REF TO facade. / 'MethodA() ----'. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. ENDMETHOD. "constructor METHOD methoda. WRITE: /. ENDCLASS.methodb . two->methodtwo( ). "methoda METHOD methodb. ENDMETHOD. WRITE: /. CLASS-METHODS: main. three->methodthree( ). facade->methodb( ). ENDCLASS. four->methodfour( ). START-OF-SELECTION. facade->methoda( ). / 'MethodB() ----'. "facade IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. PUBLIC SECTION. ENDMETHOD.Project: Design Pattern . CREATE OBJECT three. METHOD main. "methodb ENDCLASS. CREATE OBJECT two.0 Side: 115 . OUTPUT: --------MethodA() SubsystemOne Method SubsystemTwo Method SubsystemFour Method "endmethod "mainapp IMPLEMENTATION Version: 1. mainapp=>main( ). ENDCLASS. CREATE OBJECT four. two->methodtwo( ).

Read().RealWorld { // MainApp test application class MainApp { static void Main() { // Facade Mortgage mortgage = new Mortgage(). bool eligable = mortgage.WriteLine("Check bank for " + c.IsEligible(customer.Real World example using System.Name). // Evaluate mortgage eligibility for customer Customer customer = new Customer("Ann McKinsey"). // Facade pattern -. namespace DoFactory. } } // "Subsystem ClassA" class Bank { public bool HasSufficientSavings(Customer c.Name + " has been " + (eligable ? "Approved" : "Rejected")).125000).5.GangOfFour. // Wait for user Console.Project: Design Pattern MethodB() SubsystemTwo Method SubsystemThree Method 2. Console.0 Side: 116 . return true. int amount) { Console.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.WriteLine("\n" + customer.2. } } // "Subsystem ClassB" class Credit { public bool HasGoodCredit(Customer c) Version: 1.

} else if (!loan.WriteLine("Check loans for " + c. // Check creditworthyness of applicant if (!bank. // Constructor public Customer(string name) { this.HasNoBadLoans(cust)) { Version: 1.Name).name = name. return true. } } // "Subsystem ClassC" class Loan { public bool HasNoBadLoans(Customer c) { Console. } // Property public string Name { get{ return name. amount)) { eligible = false. return true.Name). bool eligible = true. private Loan loan = new Loan(). } } } // "Facade" class Mortgage { private Bank bank = new Bank(). cust.Name. } } class Customer { private string name.0 Side: 117 .WriteLine("Check credit for " + c.Project: Design Pattern { Console. int amount) { Console.HasSufficientSavings(cust. public bool IsEligible(Customer cust. private Credit credit = new Credit(). amount).WriteLine("{0} applies for {1:C} loan\n".

*----------------------------------------------------------------------* * CLASS customer DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS customer DEFINITION. PUBLIC SECTION. DATA: name TYPE string.5. } return eligible. "customer DEFINITION *----------------------------------------------------------------------* * CLASS customer IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* Version: 1. PRIVATE SECTION. *&---------------------------------------------------------------------* *& Report ZDP_FACADE_REALWORLD *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_facade_realworld.2.Project: Design Pattern eligible = false.000.0 Side: 118 . ENDCLASS.00 loan Check bank for Ann McKinsey Check loans for Ann McKinsey Check credit for Ann McKinsey Ann McKinsey has been Approved 2. METHODS: constructor IMPORTING name TYPE string . } } } Output Ann McKinsey applies for $125.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. } else if (!credit.HasGoodCredit(cust)) { eligible = false.getname RETURNING value(name) TYPE string .

"hassufficientsavings ENDCLASS. mycustomer. value = 'X'. myname = customer->getname( ). DATA: mycustomer TYPE string. name = me->name. ENDCLASS. METHOD constructor. ENDMETHOD. DATA: myname TYPE string. PUBLIC SECTION. METHOD getname. mycustomer = customer->getname( ).0 Side: 119 . METHOD hassufficientsavings. "~TRUE ENDMETHOD. "constructor "getname "customer IMPLEMENTATION *----------------------------------------------------------------------* * CLASS bank DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS bank DEFINITION. val = 'X'. METHOD hasgoodcredit.Project: Design Pattern CLASS customer IMPLEMENTATION. ENDMETHOD. METHODS: hasgoodcredit IMPORTING customer TYPE REF TO customer RETURNING value(value) TYPE boolean . "bank DEFINITION *----------------------------------------------------------------------* * CLASS bank IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS bank IMPLEMENTATION. "~true ENDMETHOD. "bank IMPLEMENTATION *----------------------------------------------------------------------* * CLASS credit DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS credit DEFINITION. myname. "hasgoodcredit Version: 1. me->name = name. WRITE: / 'Check credit for '. ENDCLASS. PUBLIC SECTION. ENDCLASS. "credit DEFINITION *----------------------------------------------------------------------* * CLASS credit IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS credit IMPLEMENTATION. WRITE: / 'Check bank for '. METHODS: hassufficientsavings IMPORTING customer TYPE REF TO customer amount TYPE i RETURNING value(val) TYPE boolean .

iseligible IMPORTING customer TYPE REF TO customer amount TYPE i RETURNING value(value) TYPE boolean . METHODS: hasnobadloans IMPORTING customer TYPE REF TO customer RETURNING value(value) TYPE boolean. ENDCLASS. "credit IMPLEMENTATION *----------------------------------------------------------------------* * CLASS loan DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS loan DEFINITION. mycustomer = customer->getname( ). WRITE: / 'Check loans for '. CREATE OBJECT loan. PUBLIC SECTION. value = 'X'. METHOD constructor. PUBLIC SECTION.0 Side: 120 . "mortgage DEFINITION *----------------------------------------------------------------------* * CLASS mortgage IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mortgage IMPLEMENTATION. ENDCLASS. mycustomer. CREATE OBJECT credit. "loan DEFINITION *----------------------------------------------------------------------* * CLASS loan IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS loan IMPLEMENTATION. "~true ENDMETHOD. Version: 1.credit TYPE REF TO credit . customername = customer->getname( ). METHOD hasnobadloans. CREATE OBJECT bank. DATA: mycustomer TYPE string. DATA: customername TYPE string. DATA: bank TYPE REF TO bank . "constructor METHOD iseligible. "hasnobadloans ENDCLASS. "loan IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mortgage DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mortgage DEFINITION.Project: Design Pattern ENDCLASS. PRIVATE SECTION. ENDMETHOD.loan TYPE REF TO loan . METHODS: constructor .

WRITE: ' Rejected '. PUBLIC SECTION. ENDMETHOD. CLASS-METHODS: main.Project: Design Pattern WRITE: / customername. ENDCLASS. ENDIF. ' Has been '. customername = customer->getname( ). IF eligible = 'X'. WRITE: ' Approved '. ENDMETHOD. CREATE OBJECT mortgage. "~false ELSEIF credit->hasgoodcredit( customer ) NE 'X'. value = '-'. value = '-'.0 Side: 121 . amount. " ~false ELSEIF loan->hasnobadloans( customer ) NE 'X'. WRITE: /. "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. value = 'X'.eligible TYPE boolean . METHOD main. ENDCLASS.customername TYPE string ./ customername. "~false ENDIF. "iseligible "mortgage IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION. ELSE. ENDCLASS. START-OF-SELECTION. "~TRUE IF bank->hassufficientsavings( customer = customer amount = amount ) NE 'X'.000 Check bank for Ann McKinsey Check loans for Ann McKinsey Check credit for Ann McKinsey Ann McKinsey Has been Approved loan Version: 1. 'loan '. "endmethod "mainapp IMPLEMENTATION OUTPUT ------------Ann McKinsey applies for 125. ' applies for '. mainapp=>main( ). DATA: mortgage TYPE REF TO mortgage . value = '-'.customer TYPE REF TO customer . eligible = mortgage->iseligible( customer = customer amount = 125000 ). CREATE OBJECT customer EXPORTING name = 'Ann McKinsey'.

if any. The Flyweight interface enables sharing.2. 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).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.6. 2..2 UML class diagram 2. CharacterZ) o implements the Flyweight interface and adds storage for intrinsic state.6 Flyweight (fluevægt) A fine-grained instance used for efficient sharing 2. it must be independent of the ConcreteFlyweight object's context... Any state it stores must be intrinsic.6.2. if none exists. but it doesn't enforce it.1 Definition Use sharing to support large numbers of fine-grained (fin kornet) objects efficiently.0 Side: 122 .6.Project: Design Pattern 2. • FlyweightFactory (CharacterFactory) o creates and manages flyweight objects ensures that flyweight are shared properly. A ConcreteFlyweight object must be sharable. • UnsharedConcreteFlyweight ( not used ) o not all Flyweight subclasses need to be shared.2. . CharacterB.2. (udefra kommende/ydre) • ConcreteFlyweight (CharacterA. the FlyweightFactory objects supplies an existing instance or creates one. (indre/indefra kommende) that is. Version: 1. When a client requests a flyweight.

6. } } // "FlyweightFactory" class FlyweightFactory { private Hashtable flyweights = new Hashtable().Operation(--extrinsicstate). // Constructor Version: 1.Collections.GangOfFour. uf. // Wait for user Console.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 fy = f. Flyweight fz = f.Flyweight. // Work with different flyweight instances Flyweight fx = f.GetFlyweight("Y"). using System.2. computes or stores the extrinsic state of flyweight(s).Operation(--extrinsicstate).Operation(--extrinsicstate).Read().Operation(--extrinsicstate). namespace DoFactory. 2. fy. UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight().Project: Design Pattern • Client (FlyweightApp) o maintains a reference to flyweight(s).GetFlyweight("Z").0 Side: 123 .GetFlyweight("X").Structural { // MainApp test application class MainApp { static void Main() { // Arbitrary extrinsic state int extrinsicstate = 22. // Flyweight pattern -. fz. FlyweightFactory f = new FlyweightFactory(). fx.Structural example using System.

} } } Output ConcreteFlyweight: 21 ConcreteFlyweight: 20 ConcreteFlyweight: 19 UnsharedConcreteFlyweight: 18 2.Add("Z".Add("X". } } // "Flyweight" abstract class Flyweight { public abstract void Operation(int extrinsicstate).Project: Design Pattern public FlyweightFactory() { flyweights. } // "ConcreteFlyweight" class ConcreteFlyweight : Flyweight { public override void Operation(int extrinsicstate) { Console.WriteLine("ConcreteFlyweight: " + extrinsicstate). flyweights.6.WriteLine("UnsharedConcreteFlyweight: " + extrinsicstate).2. new ConcreteFlyweight()).0 Side: 124 . new ConcreteFlyweight()). flyweights.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.Add("Y". } } // "UnsharedConcreteFlyweight" class UnsharedConcreteFlyweight : Flyweight { public override void Operation(int extrinsicstate) { Console. } public Flyweight GetFlyweight(string key) { return((Flyweight)flyweights[key]). *&---------------------------------------------------------------------* *& Report ZDP_FLYWEIGHT_STRUCTURAL *& Version: 1. new ConcreteFlyweight()).

"operation ENDCLASS. PUBLIC SECTION.Project: Design Pattern *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_flyweight_structural. METHODS: operation REDEFINITION. PUBLIC SECTION. ENDCLASS. extrincicstate. "concreteflyweight IMPLEMENTATION *----------------------------------------------------------------------* * CLASS unsharedconcreteflyweight DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS unsharedconcreteflyweight DEFINITION INHERITING FROM flyweight. "unsharedconcreteflyweight DEFINITION *----------------------------------------------------------------------* * CLASS unsharedconcreteflyweight IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS unsharedconcreteflyweight IMPLEMENTATION. *----------------------------------------------------------------------* * CLASS flyweight DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS flyweight DEFINITION ABSTRACT. "operation ENDCLASS. "unsharedconcreteflyweight IMPLEMENTATION *----------------------------------------------------------------------* * CLASS flyweightfactory DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* Version: 1. METHOD operation. METHOD operation. METHODS: operation ABSTRACT IMPORTING extrincicstate TYPE i. ENDCLASS. WRITE: /5(20)'ConcreteFlyweight'. WRITE: /5(20)'UnsharedConcreteFlyweight'. ENDCLASS.0 Side: 125 . "flyweight DEFINITION *----------------------------------------------------------------------* * CLASS concreteflyweight DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concreteflyweight DEFINITION INHERITING FROM flyweight. METHODS: operation REDEFINITION. "concreteflyweight DEFINITION *----------------------------------------------------------------------* * CLASS concreteflyweight IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concreteflyweight IMPLEMENTATION. extrincicstate. ENDMETHOD. PUBLIC SECTION. ENDMETHOD.

value = buffer-value. METHODS: constructor . "mainapp DEFINITION *----------------------------------------------------------------------* * CLASS mainapp IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp IMPLEMENTATION. METHOD main. TYPES: BEGIN OF ty_flyweight .Project: Design Pattern CLASS flyweightfactory DEFINITION. CREATE OBJECT cf.0 Side: 126 . "getflyweight ENDCLASS. PUBLIC SECTION. CLASS-METHODS: main. PUBLIC SECTION.value TYPE REF TO concreteflyweight . DATA buffer TYPE ty_flyweight.key(1) TYPE c .buffer TYPE ty_flyweight . METHOD constructor. "flyweightfactory IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mainapp DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mainapp DEFINITION.END OF ty_flyweight. buffer-key = 'Z'. CREATE OBJECT cf. INSERT buffer INTO TABLE flyweights. INSERT buffer INTO TABLE flyweights. buffer-key = 'Y'. INSERT buffer INTO TABLE flyweights.getflyweight IMPORTING key TYPE c RETURNING value(value) TYPE REF TO flyweight . DATA flyweights TYPE HASHED TABLE OF ty_flyweight WITH UNIQUE KEY key. ENDMETHOD. buffer-value = cf. ENDMETHOD. "constructor METHOD getflyweight. buffer-key = 'X'. READ TABLE flyweights WITH TABLE KEY key = key INTO buffer. ENDCLASS. PRIVATE SECTION. "flyweightfactory DEFINITION *----------------------------------------------------------------------* * CLASS flyweightfactory IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS flyweightfactory IMPLEMENTATION. ENDCLASS. buffer-value = cf. Version: 1. CREATE OBJECT cf. DATA: cf TYPE REF TO concreteflyweight . buffer-value = cf.

Real World example using System. subtract 1 from extrincicstate.6. CREATE OBJECT uf. extrincicstate = 22. fy->operation( extrincicstate ). ENDMETHOD.0 Side: 127 . fz = f->getflyweight( 'Z' ).Project: Design Pattern data: extrincicstate type i . uf->operation( extrincicstate ). fx->operation( extrincicstate ). namespace DoFactory. using System.Collections. fy = f->getflyweight( 'Y' ). OUTPUT: ----------------"endmethod "mainapp IMPLEMENTATION ConcreteFlyweight ConcreteFlyweight ConcreteFlyweight UnsharedConcreteFlyw 21 20 19 18 2.fx TYPE REF TO flyweight . mainapp=>main( ).Flyweight.uf TYPE REF TO unsharedconcreteflyweight .f type REF TO flyweightfactory . subtract 1 from extrincicstate. subtract 1 from extrincicstate. START-OF-SELECTION.fy TYPE REF TO flyweight . subtract 1 from extrincicstate.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 -.fz TYPE REF TO flyweight . fx = f->getflyweight( 'X' ).RealWorld { // MainApp test application Version: 1. fz->operation( extrincicstate ). CREATE OBJECT f.2.GangOfFour. ENDCLASS.

case 'B': character = new CharacterB(). } } // "Flyweight" abstract class Character { Version: 1. public Character GetCharacter(char key) { // Uses "lazy initialization" Character character = characters[key] as Character.. // extrinsic state int pointSize = 10. } return character. } } // "FlyweightFactory" class CharacterFactory { private Hashtable characters = new Hashtable().Read(). } characters.Display(pointSize). case 'Z': character = new CharacterZ(). break. } // Wait for user Console.0 Side: 128 . Character character = f. character.GetCharacter(c). break.ToCharArray(). break. // For each character use a flyweight object foreach (char c in chars) { pointSize++.Add(key. character). if (character == null) { switch (key) { case 'A': character = new CharacterA(). char[] chars = document..Project: Design Pattern class MainApp { static void Main() { // Build a document with text string document = "AAZZBBZB". CharacterFactory f = new CharacterFactory(). //.

} public override void Display(int pointSize) { this. D. Console.height = 100. this.descent = 0.pointSize = pointSize. this. } public override void Display(int pointSize) { this.ascent = 72.pointSize + ")"). Version: 1. this. E.symbol = 'A'.ascent = 70.Project: Design Pattern protected protected protected protected protected protected char symbol. } } // "ConcreteFlyweight" class CharacterB : Character { // Constructor public CharacterB() { this. this.pointSize = pointSize.WriteLine(this. int ascent. this. } } // .height = 100..width = 140. int height. int descent. C.0 Side: 129 . etc.width = 120. this. Console.pointSize + ")"). } // "ConcreteFlyweight" class CharacterA : Character { // Constructor public CharacterA() { this. public abstract void Display(int pointSize).symbol + " (pointsize " + this.symbol = 'B'. int width. this. int pointSize.descent = 0.WriteLine(this.symbol + " (pointsize " + this. this..

2. this.7 Proxy An object representing another object 2.pointSize = pointSize. Console. this. } } } Output A A Z Z B B Z B (pointsize (pointsize (pointsize (pointsize (pointsize (pointsize (pointsize (pointsize 11) 12) 13) 14) 15) 16) 17) 18) 2. } public override void Display(int pointSize) { this.2.WriteLine(this.ascent = 68. this.width = 100.1 Definition Provide a surrogate or placeholder for another object to control access to it.7.pointSize + ")").symbol + " (pointsize " + this. Version: 1.symbol = 'Z'.height = 100.Project: Design Pattern // "ConcreteFlyweight" class CharacterZ : Character { // Constructor public CharacterZ() { this.descent = 0.0 Side: 130 . this.

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. 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.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.2 UML class diagram 2. • RealSubject (Math) o defines the real object that the proxy represents.0 Side: 131 .Project: Design Pattern 2.2.Structural example Version: 1.2. controls access to the real subject and may be responsible for creating and deleting it.2.7. For example. protection proxies check that the caller has the access permissions required to perform a request. virtual proxies may cache additional information about the real subject so that they can postpone accessing it. provides an interface identical to Subject's so that a proxy can be substituted for for the real subject. the ImageProxy from the Motivation caches the real images's extent. 2. Proxy may refer to a Subject if the RealSubject and Subject interfaces are the same. // Proxy pattern -.7. • Subject (IMath) o defines the common interface for RealSubject and Proxy so that a Proxy can be used anywhere a RealSubject is expected.

Request().Proxy. } } // "Proxy" class Proxy : Subject { RealSubject realSubject.0 Side: 132 . } // "RealSubject" class RealSubject : Subject { public override void Request() { Console.Structural { // MainApp test application class MainApp { static void Main() { // Create proxy and request a service Proxy proxy = new Proxy(). proxy.Read().Request().Request()"). namespace DoFactory. // Wait for user Console. public override void Request() { // Use 'lazy initialization' if (realSubject == null) { realSubject = new RealSubject(). } } // "Subject" abstract class Subject { public abstract void Request(). } realSubject.GangOfFour. } } } Version: 1.Project: Design Pattern using System.WriteLine("Called RealSubject.

METHODS: Version: 1. PUBLIC SECTION.Request()'. WRITE: / 'Called RealSubject. "realsubject DEFINITION *----------------------------------------------------------------------* * CLASS realsubject IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS realsubject IMPLEMENTATION. "request ENDCLASS. "realsubject IMPLEMENTATION *----------------------------------------------------------------------* * CLASS proxy DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS proxy DEFINITION INHERITING FROM subject. "subject DEFINITION *----------------------------------------------------------------------* * CLASS realsubject DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS realsubject DEFINITION INHERITING FROM subject. DATA: realsubject TYPE REF TO realsubject.Request() 2. METHODS: request REDEFINITION. PUBLIC SECTION. METHODS: request ABSTRACT. ENDCLASS.2. ENDCLASS.0 Side: 133 . *----------------------------------------------------------------------* * CLASS subject DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS subject DEFINITION ABSTRACT. METHOD request. PUBLIC SECTION.5 Sample code In ABAP *&---------------------------------------------------------------------* *& Report ZDP_PROXY_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_proxy_structural.7.Project: Design Pattern Output Called RealSubject. ENDMETHOD.

CATCH cx_sy_create_object_error INTO exc_ref. *---------------------------------------------------------* LCL_APPLICATION->RUN(). CREATE OBJECT proxy. Version: 1. *---------------------------------------------------------METHOD run. MESSAGE exc_text TYPE 'I'. PRIVATE SECTION. "request ENDCLASS. CREATE OBJECT realsubject.0 Side: 134 . * Use the constructor for instantiating internal objects. ENDMETHOD.exc_text TYPE string. CLASS-METHODS: run. METHODS: constructor. ENDCLASS. ENDIF. * use lazy initialization IF me->realsubject IS INITIAL. tables and events. ENDMETHOD. me->realsubject->request( ). CREATE OBJECT lcl_application=>so_application. IF lcl_application=>so_application IS INITIAL.Project: Design Pattern request REDEFINITION. "proxy DEFINITION *----------------------------------------------------------------------* * CLASS proxy IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS proxy IMPLEMENTATION. exc_text = exc_ref->get_text( ). "proxy IMPLEMENTATION *---------------------------------------------------------* CLASS lcl_application DEFINITION *---------------------------------------------------------CLASS lcl_application DEFINITION CREATE PRIVATE. TRY. "lcl_application DEFINITION *---------------------------------------------------------* IMPLEMENTATION *---------------------------------------------------------CLASS lcl_application IMPLEMENTATION. PUBLIC SECTION. DATA: proxy TYPE REF TO proxy. ENDIF. CLASS-DATA: so_application TYPE REF TO lcl_application. "run *---------------------------------------------------------* LCL_APPLICATION->CONSTRUCTOR(). DATA: exc_ref TYPE REF TO cx_root . * fields. ENDTRY. METHOD request. ENDCLASS. *---------------------------------------------------------METHOD constructor.

2. START-OF-SELECTION. // Proxy pattern -. } } // "Subject" public interface IMath { double Add(double x.Proxy.RealWorld { // Mainapp test application class MainApp { static void Main() { // Create math proxy MathProxy p = new MathProxy().WriteLine("4 // Wait for user Console.Real World example using System. double y).Div(4. p. + * / 2 2 2 2 = = = = " " " " + + + + p.WriteLine("4 Console.GangOfFour. 2)). ENDMETHOD. 2)). 2)). p.WriteLine("4 Console.Request() "constructor "lcl_application IMPLEMENTATION 2.WriteLine("4 Console.Mul(4. namespace DoFactory.Read(). double y). Version: 1.Add(4. Output: Program ZDP_PROXY_STRUCTURAL Called RealSubject. // Do the math Console.6 Sample code In C# This real-world code demonstrates the Proxy pattern for a Math object represented by a MathProxy object. double Sub(double x.7. p.0 Side: 135 . double y).Sub(4.Project: Design Pattern proxy->request( ). double Mul(double x. ENDCLASS. 2)). lcl_application=>run( ).

double y) x.2.7 Sample code In ABAP using interface This real-world code demonstrates the Proxy pattern for a Math object represented by a MathProxy object.Project: Design Pattern double Div(double x.y).y). double y).Mul(x. } public double Div(double { return math. x.0 Side: 136 . } public double Sub(double { return math. x.} y. public MathProxy() { math = new Math(). double y) x. } public double Mul(double { return math.} y.Sub(x. double y) Output 4 4 4 4 + * / 2 2 2 2 = = = = 6 2 8 2 2. double double double double y){return y){return y){return y){return x x x x + * / y. x. } // "RealSubject" class Math : IMath { public double Add(double public double Sub(double public double Mul(double public double Div(double } // "Proxy Object" class MathProxy : IMath { Math math. *&---------------------------------------------------------------------* *& Report ZDP_PROXY_REALWORLD Version: 1.y).} y.y). } } } x.Div(x.} x.Add(x. double y) x.7. } public double Add(double { return math.

ALIASES: add FOR if_math~add . METHOD add. "div ENDCLASS.sub IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i . v = x . ENDMETHOD. ENDCLASS.div FOR if_math~div. v = x + y.y. "if_math *----------------------------------------------------------------------* * CLASS math DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS math DEFINITION. ENDMETHOD. v = x DIV y. METHODS: add IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i . PUBLIC SECTION. "sub METHOD mul. ENDMETHOD.mul IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i . *----------------------------------------------------------------------* * INTERFACE if_math *----------------------------------------------------------------------* * *----------------------------------------------------------------------* INTERFACE if_math.0 Side: 137 . v = x * y. ENDINTERFACE. "mul METHOD div. INTERFACES: if_math.mul FOR if_math~mul .div IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i . "math IMPLEMENTATION *----------------------------------------------------------------------* * CLASS mathproxy DEFINITION Version: 1.Project: Design Pattern *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_proxy_realworld.sub FOR if_math~sub . ENDMETHOD. "math DEFINITION *----------------------------------------------------------------------* * CLASS math IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS math IMPLEMENTATION. "add METHOD sub.

ENDCLASS. ENDMETHOD. PUBLIC SECTION. v = math->div( x = x y = y ).0 Side: 138 . ENDMETHOD. "mathproxy DEFINITION *----------------------------------------------------------------------* * CLASS mathproxy IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mathproxy IMPLEMENTATION.mul FOR if_math~mul . DATA: math TYPE REF TO math. v = math->add( x = x y = y ). Version: 1. PRIVATE SECTION. v = math->sub( x = x y = y ). ENDMETHOD. ENDCLASS. PUBLIC SECTION. ENDMETHOD. INTERFACES: if_math. CREATE OBJECT math.div FOR if_math~div. "sub METHOD mul. "mul METHOD div. METHODS: constructor. ALIASES: add FOR if_math~add . "constructor METHOD add. ENDMETHOD. "add METHOD sub. v = math->mul( x = x y = y ). METHOD constructor.Project: Design Pattern *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS mathproxy DEFINITION.sub FOR if_math~sub . METHODS: constructor. "lcl_application DEFINITION *---------------------------------------------------------* IMPLEMENTATION *---------------------------------------------------------CLASS lcl_application IMPLEMENTATION. "div ENDCLASS. CLASS-METHODS: run. CLASS-DATA: so_application TYPE REF TO lcl_application. "mathproxy IMPLEMENTATION *----------------------------------------------------------------------* *---------------------------------------------------------* CLASS lcl_application DEFINITION *---------------------------------------------------------CLASS lcl_application DEFINITION CREATE PRIVATE. *---------------------------------------------------------* LCL_APPLICATION->RUN().

result = p->mul( x = 4 y = 2 ). A way of passing a request between a chain of objects 2. WRITE:/ '4 + 2 = '. lcl_application=>run( ). WRITE:/ '4 * 2 = '.1 Definition Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. tables and events. "lcl_application IMPLEMENTATION 2. Chain the receiving objects and pass Version: 1. CATCH cx_sy_create_object_error INTO exc_ref. CREATE OBJECT p. DATA: exc_ref TYPE REF TO cx_root . WRITE:/ '4 / 2 = '. * do the math result = p->add( x = 4 y = 2 ). *---------------------------------------------------------METHOD constructor. result. * fields.3 Behavioral Patterns 2. ENDMETHOD.Project: Design Pattern *---------------------------------------------------------METHOD run. START-OF-SELECTION. result. result = p->sub( x = 4 y = 2 ).1. "constructor ENDCLASS. WRITE:/ '4 . TRY.1 Chain of Resp. * Use the constructor for instantiating internal objects.3. DATA: p TYPE REF TO mathproxy . exc_text = exc_ref->get_text( ). ENDIF.result TYPE i .0 Side: 139 .2 = '. ENDMETHOD. CREATE OBJECT lcl_application=>so_application. result = p->div( x = 4 y = 2 ).3. ENDTRY. result.exc_text TYPE string. result. IF lcl_application=>so_application IS INITIAL. MESSAGE exc_text TYPE 'I'. "run *---------------------------------------------------------* LCL_APPLICATION->CONSTRUCTOR().

2 UML class diagram 2. otherwise it forwards the request to its successor • Client (ChainApp) o initiates the request to a ConcreteHandler object on the chain 2.1.Structural { // MainApp test application class MainApp { static void Main() { // Setup Chain of Responsibility Handler h1 = new ConcreteHandler1(). it does so.Project: Design Pattern the request along the chain until an object handles it.3.3.Structural example using System. President) o handles requests it is responsible for can access its successor if the ConcreteHandler can handle the request. // Chain of Responsibility pattern -. VicePresident.GangOfFour. Handler h3 = new ConcreteHandler3().1. Version: 1.3. Handler h2 = new ConcreteHandler2().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. The client do know which of the receiver that are the first I the chain. 2.0 Side: 140 .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.1.Chain. namespace DoFactory.

3.GetType(). } // Wait for user Console. request). } } } // "ConcreteHandler2" class ConcreteHandler2 : Handler { public override void HandleRequest(int request) { if (request >= 10 && request < 20) { Version: 1. } } // "Handler" abstract class Handler { protected Handler successor.Read(). 22. 5. 20}. this. foreach (int request in requests) { h1. // Generate and process request int[] requests = {2.HandleRequest(request). } class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Console. } else if (successor != null) { successor.WriteLine("{0} handled request {1}".SetSuccessor(h2). } public abstract void HandleRequest(int request).HandleRequest(request).Name. 27. public void SetSuccessor(Handler successor) { this. 18.successor = successor.Project: Design Pattern h1. 14.SetSuccessor(h3).0 Side: 141 . h2.

Version: 1.Name. CLASS cl_abap_typedescr DEFINITION LOAD.WriteLine("{0} handled request {1}".3. } else if (successor != null) { successor.GetType().HandleRequest(request).0 Side: 142 .Name. } } } } Output ConcreteHandler1 ConcreteHandler1 ConcreteHandler2 ConcreteHandler3 ConcreteHandler2 ConcreteHandler1 ConcreteHandler3 ConcreteHandler3 handled handled handled handled handled handled handled handled request request request request request request request request 2 5 14 22 18 3 27 20 2.Project: Design Pattern Console. } else if (successor != null) { successor. *&---------------------------------------------------------------------* *& Report ZDP_CHAINOFRESP_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_chainofresp_structural.GetType(). request). this.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.WriteLine("{0} handled request {1}".HandleRequest(request). request). this. } } } // "ConcreteHandler3" class ConcreteHandler3 : Handler { public override void HandleRequest(int request) { if (request >= 20 && request < 30) { Console.

slen TYPE i . "setsuccessor ENDCLASS. me->successor = successor. METHODS: setsuccessor IMPORTING successor TYPE REF TO handler . PUBLIC SECTION. "concretehandler1 DEFINITION *----------------------------------------------------------------------* * CLASS concretehandler1 IMPLEMENTATION Version: 1.Project: Design Pattern *----------------------------------------------------------------------* * Global Data *----------------------------------------------------------------------* DATA: moff TYPE i . "handler IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concretehandler1 DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretehandler1 DEFINITION INHERITING FROM handler. PUBLIC SECTION. &2 = cl_abap_classdescr=>get_class_name( &1 ). PROTECTED SECTION. shift &2 by slen places left. ENDCLASS. "handler DEFINITION *----------------------------------------------------------------------* * CLASS handler IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS handler IMPLEMENTATION. METHODS: handlerequest REDEFINITION. find regex 'CLASS=' in &2 match offset moff match length mlen. END-OF-DEFINITION. slen = moff + mlen. ENDMETHOD.handlerequest ABSTRACT IMPORTING request TYPE i . ENDCLASS.0 Side: 143 . DATA: successor TYPE REF TO handler.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. METHOD setsuccessor. *----------------------------------------------------------------------* * CLASS handler DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS handler DEFINITION ABSTRACT.

METHOD handlerequest. ENDMETHOD. "handlerequest ENDCLASS. ENDCLASS. 'Handled request'. WRITE: / class_name. ENDIF. IF ( request >= 0 AND request < 10 ). ENDMETHOD. "handlerequest ENDCLASS. DATA: class_name TYPE abap_abstypename.0 Side: 144 . METHODS: handlerequest REDEFINITION. "concretehandler2 DEFINITION *----------------------------------------------------------------------* * CLASS concretehandler2 IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretehandler2 IMPLEMENTATION. "concretehandler1 IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concretehandler2 DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretehandler2 DEFINITION INHERITING FROM handler. ELSEIF ( NOT successor IS INITIAL ). IF ( request >= 10 AND request < 20 ). "concretehandler2 IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concretehandler3 DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretehandler3 DEFINITION INHERITING FROM handler. ENDIF. 'Handled request'. DATA: class_name TYPE abap_abstypename. request. PUBLIC SECTION. me->successor->handlerequest( request ).Project: Design Pattern *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretehandler1 IMPLEMENTATION. WRITE: / class_name. request. me->successor->handlerequest( request ). ?get_class_name me class_name. ?get_class_name me class_name. ENDCLASS. METHOD handlerequest. "concretehandler3 DEFINITION *----------------------------------------------------------------------* * CLASS concretehandler3 IMPLEMENTATION *----------------------------------------------------------------------* * Version: 1. METHODS: handlerequest REDEFINITION. PUBLIC SECTION. ELSEIF ( NOT successor IS INITIAL ).

0 Side: 145 . request. ENDTRY. ENDCLASS. *---------------------------------------------------------METHOD run. exc_text = exc_ref->get_text( ). CLASS-DATA: so_application TYPE REF TO lcl_application. *---------------------------------------------------------* LCL_APPLICATION->RUN(). DATA: h1 TYPE REF TO concretehandler1 . METHODS: constructor. IF ( request >= 20 AND request < 30 ). DATA: exc_ref TYPE REF TO cx_root . * fields. "concretehandler3 IMPLEMENTATION *---------------------------------------------------------* CLASS lcl_application DEFINITION *---------------------------------------------------------CLASS lcl_application DEFINITION CREATE PRIVATE. *---------------------------------------------------------METHOD constructor. ENDMETHOD. CREATE OBJECT lcl_application=>so_application.Project: Design Pattern *----------------------------------------------------------------------* CLASS concretehandler3 IMPLEMENTATION. CLASS-METHODS: run. tables and events.h2 TYPE REF TO concretehandler2 . DATA: class_name TYPE abap_abstypename. PRIVATE SECTION. * Use the constructor for instantiating internal objects. METHOD handlerequest. TRY. me->successor->handlerequest( request ). ELSEIF ( NOT successor IS INITIAL ). "handlerequest ENDCLASS. ENDIF. ?get_class_name me class_name. 'Handled request'. PUBLIC SECTION. "run *---------------------------------------------------------* LCL_APPLICATION->CONSTRUCTOR(). CATCH cx_sy_create_object_error INTO exc_ref. ENDIF. "lcl_application DEFINITION *---------------------------------------------------------* IMPLEMENTATION *---------------------------------------------------------CLASS lcl_application IMPLEMENTATION. ENDMETHOD.exc_text TYPE string.h3 TYPE REF TO concretehandler3 Version: 1. MESSAGE exc_text TYPE 'I'. WRITE: / class_name. IF lcl_application=>so_application IS INITIAL.

namespace DoFactory. t_request. LOOP AT t_request INTO request.3.request TYPE i . h2->setsuccessor( h3 ). Each position has can have its own set of rules which orders they can approve.RealWorld { // MainApp test application class MainApp { static void Main() { // Setup Chain of Responsibility Director Larry = new Director(). h1->handlerequest( request ).t_request TYPE TABLE OF i . President Tammy = new President(). Larry. h1->setsuccessor( h2 ). ENDLOOP. t_request. ENDCLASS. OBJECT h3.GangOfFour. "constructor "lcl_application IMPLEMENTATION 2. * create CREATE CREATE CREATE objects OBJECT h1. t_request. t_request.1. START-OF-SELECTION. t_request. t_request. Version: 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.0 Side: 146 . OBJECT h2.SetSuccessor(Sam). t_request. ENDMETHOD. INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT 2 5 14 22 18 3 27 20 INTO INTO INTO INTO INTO INTO INTO INTO TABLE TABLE TABLE TABLE TABLE TABLE TABLE TABLE t_request. VicePresident Sam = new VicePresident(). // Chain of Responsibility pattern -. lcl_application=>run( ).Chain.Project: Design Pattern .Real World example using System.

ProcessRequest(purchase). Larry.00. } else if (successor != null) { successor. // Generate and process purchase requests Purchase p = new Purchase(2034. } // "ConcreteHandler" class Director : Approver { public override void ProcessRequest(Purchase purchase) { if (purchase.Amount < 25000. this. Larry. p = new Purchase(2035.ProcessRequest(p). 32590.00.Read().successor = successor.Name. } public abstract void ProcessRequest(Purchase purchase). "Project Y"). 122100. "Project X"). "Supplies").0 Side: 147 .ProcessRequest(p). Larry.0) Version: 1. public void SetSuccessor(Approver successor) { this.Amount < 10000.SetSuccessor(Tammy). purchase.ProcessRequest(p). 350. p = new Purchase(2036.Project: Design Pattern Sam.Number). // Wait for user Console.0) { Console.GetType().WriteLine("{0} approved request# {1}". } } // "Handler" abstract class Approver { protected Approver successor.10. } } } // "ConcreteHandler" class VicePresident : Approver { public override void ProcessRequest(Purchase purchase) { if (purchase.

WriteLine( "Request# {0} requires an executive meeting!". this.Amount < 100000. } } } // Request details class Purchase { private int number. } set{ amount = value. } else { Console. purchase.Number).WriteLine("{0} approved request# {1}". } // Properties public double Amount { get{ return amount.Number).WriteLine("{0} approved request# {1}".Number).Project: Design Pattern { Console.0) { Console. purchase.amount = amount. private double amount.Name.GetType(). } } } // "ConcreteHandler" class President : Approver { public override void ProcessRequest(Purchase purchase) { if (purchase.GetType(). } } public string Purpose { Version: 1. } else if (successor != null) { successor.0 Side: 148 . private string purpose. // Constructor public Purchase(int number. purchase.ProcessRequest(purchase). this. this. string purpose) { this.Name. double amount.number = number.purpose = purpose. this.

slen = moff + mlen. } set{ purpose = value. Each position has can have its own set of rules which orders they can approve. shift &2 by slen places left.slen TYPE i . } } public int Number { get{ return number.0 Side: 149 . *&---------------------------------------------------------------------* *& Report ZDP_CHAINOFRESP_REALWORLD *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_chainofresp_realworld.3.1. &2 = cl_abap_classdescr=>get_class_name( &1 ). } set{ number = value. find regex 'CLASS=' in &2 match offset moff match length mlen.Project: Design Pattern get{ return purpose.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.mlen TYPE i. CLASS cl_abap_typedescr DEFINITION LOAD. *----------------------------------------------------------------------* * CLASS purchase DEFINITION *----------------------------------------------------------------------* Version: 1. END-OF-DEFINITION. *----------------------------------------------------------------------* * Global Data *----------------------------------------------------------------------* DATA: moff TYPE i . } } } } Output Director Larry approved request# 2034 President Tammy approved request# 2035 Request# 2036 requires an executive meeting! 2. *----------------------------------------------------------------------* * 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.

METHODS: constructor IMPORTING number TYPE i amount TYPE f purpose TYPE string . CASE name.setsuccessor IMPORTING successor TYPE REF TO approver .purpose TYPE string . "approver DEFINITION *----------------------------------------------------------------------* Version: 1.amount TYPE f . "purchase IMPLEMENTATION *----------------------------------------------------------------------* * CLASS approver DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS approver DEFINITION ABSTRACT. "get_property ENDCLASS. GET REFERENCE OF me->number INTO dref. ENDMETHOD.Project: Design Pattern * *----------------------------------------------------------------------* CLASS purchase DEFINITION. PROTECTED SECTION. WHEN 'AMOUNT'. ENDCLASS. GET REFERENCE OF me->amount INTO dref. ENDCASE. "purchase DEFINITION *----------------------------------------------------------------------* * CLASS purchase IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS purchase IMPLEMENTATION. PRIVATE SECTION. PUBLIC SECTION.processrequest ABSTRACT IMPORTING purchase TYPE REF TO purchase . DATA: name TYPE string. "constructor METHOD get_property. GET REFERENCE OF me->purpose INTO dref. METHODS: constructor IMPORTING name TYPE string . PUBLIC SECTION. ENDCLASS. DATA: successor TYPE REF TO approver.get_property IMPORTING name TYPE string RETURNING value(dref) TYPE REF TO data. ENDMETHOD.0 Side: 150 . DATA: number TYPE i . WHEN 'PURPOSE'. me->purpose = purpose. me->number = number. WHEN 'NUMBER'. METHOD constructor. me->amount = amount.

ELSE. "Director IMPLEMENTATION *----------------------------------------------------------------------* * CLASS VicePresident DEFINITION *----------------------------------------------------------------------* Version: 1. lv_dref = purchase->get_property( 'NUMBER' ). IF NOT me->successor IS INITIAL. "approver IMPLEMENTATION *----------------------------------------------------------------------* * CLASS Director DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS director DEFINITION INHERITING FROM approver. ENDMETHOD. "constructor METHOD setsuccessor. "Director DEFINITION *----------------------------------------------------------------------* * CLASS Director IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS director IMPLEMENTATION. ENDIF. METHOD processrequest. me->successor->processrequest( purchase ). ASSIGN lv_dref->* TO <fs_number>. ASSIGN lv_dref->* TO <fs_amount>. me>name. PUBLIC SECTION. ?get_class_name me class_name. ENDMETHOD.Project: Design Pattern * CLASS approver IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS approver IMPLEMENTATION.lv_dref TYPE REF TO data. "SetSuccessor ENDCLASS. ENDIF. "ProcessRequest ENDCLASS. 'Approved request'. <fs_number> USING EDIT MASK '____' . ENDMETHOD.<fs_number> TYPE i. ENDCLASS. me->name = name. FIELD-SYMBOLS: <fs_amount> TYPE f . lv_dref = purchase->get_property( 'AMOUNT' ). me->successor = successor. IF <fs_amount> < 10000. METHOD constructor. DATA: class_name TYPE abap_abstypename .0 Side: 151 . WRITE: / class_name. METHODS: processrequest REDEFINITION.

METHODS: processrequest REDEFINITION. ?get_class_name me class_name.Project: Design Pattern * *----------------------------------------------------------------------* CLASS vicepresident DEFINITION INHERITING FROM approver. 'Approved request'. IF <fs_amount> < 25000. METHODS: processrequest REDEFINITION. me>name. "ProcessRequest ENDCLASS.0 Side: 152 .<fs_number> TYPE i. ENDIF. DATA: class_name TYPE abap_abstypename . ENDCLASS. lv_dref = purchase->get_property( 'NUMBER' ). ENDCLASS. ASSIGN lv_dref->* TO <fs_number>. "VicePresident DEFINITION *----------------------------------------------------------------------* * CLASS VicePresident IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS vicepresident IMPLEMENTATION. "President DEFINITION *----------------------------------------------------------------------* * CLASS President IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS president IMPLEMENTATION. ENDMETHOD. <fs_number> USING EDIT MASK '____'. FIELD-SYMBOLS: <fs_amount> TYPE f Version: 1. WRITE: / class_name. ENDIF. PUBLIC SECTION. me->successor->processrequest( purchase ). METHOD processrequest. ASSIGN lv_dref->* TO <fs_amount>. IF NOT me->successor IS INITIAL.lv_dref TYPE REF TO data. PUBLIC SECTION. FIELD-SYMBOLS: <fs_amount> TYPE f . "VicePresident IMPLEMENTATION *----------------------------------------------------------------------* * CLASS President DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS president DEFINITION INHERITING FROM approver. METHOD processrequest. lv_dref = purchase->get_property( 'AMOUNT' ). ELSE.

"run *---------------------------------------------------------* LCL_APPLICATION->CONSTRUCTOR(). "President IMPLEMENTATION *---------------------------------------------------------* CLASS lcl_application DEFINITION *---------------------------------------------------------CLASS lcl_application DEFINITION CREATE PRIVATE. ENDTRY. "lcl_application DEFINITION *---------------------------------------------------------* IMPLEMENTATION *---------------------------------------------------------CLASS lcl_application IMPLEMENTATION.Project: Design Pattern . Version: 1. 'Requires an executive meeting'. lv_dref = purchase->get_property( 'NUMBER' ). ENDIF. IF lcl_application=>so_application IS INITIAL. DATA: class_name TYPE abap_abstypename . *---------------------------------------------------------METHOD run. ENDMETHOD. me>name.lv_dref TYPE REF TO data. lv_dref = purchase->get_property( 'AMOUNT' ). CREATE OBJECT lcl_application=>so_application. *---------------------------------------------------------* LCL_APPLICATION->RUN(). ELSE. CATCH cx_sy_create_object_error INTO exc_ref. ENDMETHOD. CLASS-METHODS: run. 'Approved request'. ASSIGN lv_dref->* TO <fs_amount>. ASSIGN lv_dref->* TO <fs_number>. METHODS: constructor. CLASS-DATA: so_application TYPE REF TO lcl_application. DATA: exc_ref TYPE REF TO cx_root . TRY.exc_text TYPE string. me>name. MESSAGE exc_text TYPE 'I'. ?get_class_name me class_name. ENDCLASS. IF <fs_amount> < 100000. exc_text = exc_ref->get_text( ). WRITE: / class_name. "ProcessRequest ENDCLASS.<fs_number> TYPE i. ENDIF. PRIVATE SECTION. WRITE: / class_name. <fs_number> USING EDIT MASK '____'.0 Side: 153 . <fs_number> USING EDIT MASK '____'. PUBLIC SECTION.

3. BREAK-POINT. ENDMETHOD.tammy TYPE REF TO president . "constructor "lcl_application IMPLEMENTATION 2. CREATE OBJECT p EXPORTING number = 2036 amount = '122100. Version: 1.sam TYPE REF TO vicepresident . larry->processrequest( p ). larry->processrequest( p ). CREATE OBJECT p EXPORTING number = 2034 amount = 350 purpose = 'Supplies'.2 Command Encapsulate a command request as an object 2.0 Side: 154 .2. larry->setsuccessor( sam ). tables and events. CREATE OBJECT larry EXPORTING name = 'Larry' . sam->setsuccessor( tammy ). ENDCLASS.Project: Design Pattern * Use the constructor for instantiating internal objects. thereby letting you parameterize clients with different requests. and support undoable operations.00' purpose = 'Project Y'.3. lcl_application=>run( ). larry->processrequest( p ). DATA: larry TYPE REF TO director . queue or log requests. CREATE OBJECT sam EXPORTING name = 'Sam'.10' purpose = 'Project X'. *---------------------------------------------------------METHOD constructor.p TYPE REF TO purchase . START-OF-SELECTION. * fields.1 Definition Encapsulate a request as an object. CREATE OBJECT p EXPORTING number = 2035 amount = '32590. CREATE OBJECT tammy EXPORTING name = 'Tammy'.

• • • 2.2.Command.3.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.GangOfFour.Structural example using System.2. namespace DoFactory.Structural { // MainApp test applicatio class MainApp { static void Main() Version: 1.3. // Command pattern -.0 Side: 155 .2 UML class diagram 2.2.3.Project: Design Pattern 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.

WriteLine("Called Receiver. Command command = new ConcreteCommand(receiver). command.SetCommand(command). } } // "Command" abstract class Command { protected Receiver receiver.Read().ExecuteCommand().receiver = receiver. invoker.0 Side: 156 . } } Version: 1.Action(). // Wait for user Console. } public abstract void Execute(). } // "ConcreteCommand" class ConcreteCommand : Command { // Constructor public ConcreteCommand(Receiver receiver) : base(receiver) { } public override void Execute() { receiver.Project: Design Pattern { // Create receiver.Action()"). } } // "Receiver" class Receiver { public void Action() { Console. // Set and execute command invoker. and invoker Receiver receiver = new Receiver(). Invoker invoker = new Invoker(). // Constructor public Command(Receiver receiver) { this.

} } } Output Called Receiver.Project: Design Pattern // "Invoker" class Invoker { private Command command.0 Side: 157 . ENDCLASS.Action()'. WRITE: / 'Console. ENDMETHOD. } public void ExecuteCommand() { command.Execute().WriteLine(Called Receiver. METHODS: action.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.command = command.Action() 2.2. *&---------------------------------------------------------------------* *& Report ZDP_COMMAND_STRUCTURAL *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------* REPORT zdp_command_structural. "receiver DEFINITION *----------------------------------------------------------------------* * CLASS receiver IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS receiver IMPLEMENTATION. PUBLIC SECTION. METHOD action. "action Version: 1. *----------------------------------------------------------------------* * CLASS receiver DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS receiver DEFINITION. public void SetCommand(Command command) { this.3.

DATA: receiver TYPE REF TO receiver. "receiver IMPLEMENTATION *----------------------------------------------------------------------* * CLASS command DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS command DEFINITION ABSTRACT. METHODS: constructor IMPORTING receiver TYPE REF TO receiver . "execute ENDCLASS. METHOD constructor. ENDMETHOD. "command DEFINITION *----------------------------------------------------------------------* * CLASS command IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS command IMPLEMENTATION. PUBLIC SECTION. ENDCLASS. PROTECTED SECTION. METHODS: setcommand IMPORTING command TYPE REF TO command . me->receiver->action( ). PUBLIC SECTION. ENDMETHOD. METHODS: execute REDEFINITION. "concretecommand DEFINITION *----------------------------------------------------------------------* * CLASS concretecommand IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretecommand IMPLEMENTATION.Project: Design Pattern ENDCLASS.execute ABSTRACT. "constructor ENDCLASS. me->receiver = receiver. ENDCLASS. "concretecommand IMPLEMENTATION *----------------------------------------------------------------------* * CLASS invoker DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS invoker DEFINITION. METHOD execute. PRIVATE SECTION.executecommand . Version: 1.0 Side: 158 . "command IMPLEMENTATION *----------------------------------------------------------------------* * CLASS concretecommand DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS concretecommand DEFINITION INHERITING FROM command. PUBLIC SECTION.

CATCH cx_sy_create_object_error INTO exc_ref. tables and events. me->command->execute( ). * fields. * Use the constructor for instantiating internal objects. *---------------------------------------------------------METHOD run. CLASS-DATA: so_application TYPE REF TO lcl_application. DATA: receiver TYPE REF TO receiver . *---------------------------------------------------------METHOD constructor. ENDCLASS. CREATE OBJECT lcl_application=>so_application. "run *---------------------------------------------------------* LCL_APPLICATION->CONSTRUCTOR(). CLASS-METHODS: run. *---------------------------------------------------------* LCL_APPLICATION->RUN(). METHODS: constructor. TRY. "executecommand ENDCLASS. ENDMETHOD. METHOD setcommand. ENDIF. ENDMETHOD. "lcl_application DEFINITION *---------------------------------------------------------* IMPLEMENTATION *---------------------------------------------------------CLASS lcl_application IMPLEMENTATION. DATA: exc_ref TYPE REF TO cx_root . exc_text = exc_ref->get_text( ).0 Side: 159 . "invoker DEFINITION *----------------------------------------------------------------------* * CLASS invoker IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS invoker IMPLEMENTATION. ENDTRY. ENDCLASS. PRIVATE SECTION. ENDMETHOD. "invoker IMPLEMENTATION *---------------------------------------------------------* CLASS lcl_application DEFINITION *---------------------------------------------------------CLASS lcl_application DEFINITION CREATE PRIVATE.Project: Design Pattern DATA: command TYPE REF TO command.command TYPE REF TO concretecommand Version: 1. IF lcl_application=>so_application IS INITIAL.exc_text TYPE string. PUBLIC SECTION. me->command = command. MESSAGE exc_text TYPE 'I'. "setcommand METHOD executecommand.

Project: Design Pattern .GangOfFour. user. 50). * set and execute command invoker->setcommand( command ).Action() "constructor "lcl_application IMPLEMENTATION 2. 100).Compute('-'. user. ENDMETHOD.Compute('/'.2.Compute('*'. Note that in C# the word 'operator' is a keyword.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. CREATE OBJECT receiver. invoker->executecommand( ). Output: Program ZDP_COMMAND_STRUCTURAL Console. using System. lcl_application=>run( ). // Undo 4 commands user.invoker TYPE REF TO invoker. START-OF-SELECTION. Prefixing it with '@' allows using it as an identifier. CREATE OBJECT invoker.WriteLine(Called Receiver. CREATE OBJECT command EXPORTING receiver = receiver . user. // Command pattern -.Compute('+'. ENDCLASS. Version: 1.Command.RealWorld { // MainApp test application class MainApp { static void Main() { // Create user and let her compute User user = new User(). // Redo 3 commands user. 10). user.Redo(3).Real World example using System.0 Side: 160 .Collections.Undo(4). namespace DoFactory.

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 '+': case '-': case '*': case '/': default : undo undo undo undo undo = = = = = '-'; '+'; '/'; '*'; ' '; break; break; break; break; 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 Current Current Current value value value value = 100 (following + 100) = 50 (following - 50) = 500 (following * 10) = 250 (following / 2)

---- Undo 4 levels Current value = 500 Current value = 50 Current value = 100 Current value = 0

(following (following (following (following

* / + -

2) 10) 50) 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

l_operand = _operand->get( ). PUBLIC SECTION. me->calculator = calculator. ENDMETHOD. ENDMETHOD. "execute METHOD unexecute._operand TYPE REF TO zcl_integer . PRIVATE SECTION. ENDCLASS. me->_operator->set( operator ). METHODS: constructor IMPORTING calculator TYPE REF TO calculator operator TYPE char1 operand TYPE i . ENDMETHOD. DATA: l_operand TYPE integer . "constructor METHOD operator. me->_operator->set( operator ). super->constructor( ).0 Side: 165 . ENDMETHOD.unexecute REDEFINITION . CREATE OBJECT me->_operator. l_operand = _operand->get( ).Project: Design Pattern CLASS calculatorcommand DEFINITION INHERITING FROM command._operator TYPE REF TO zcl_char . CREATE OBJECT me->_operand.execute REDEFINITION . "operand METHOD execute. Version: 1. METHOD constructor. DATA: calculator TYPE REF TO calculator . l_operator = _operator->get( ). DATA: l_operator TYPE char1 . me->_operand->set( operand ). METHODS: undo IMPORTING operator TYPE char1 RETURNING value(newoperator) TYPE char1.operand IMPORTING operand TYPE i .l_operand TYPE integer. me->_operand->set( operand ).operator IMPORTING operator TYPE char1 . me->calculator->operation( operator = l_operator operand = l_operand ). "operator METHOD operand. "calculatorcommand DEFINITION *----------------------------------------------------------------------* * CLASS calculatorcommand IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS calculatorcommand IMPLEMENTATION.l_operator TYPE char1 .

PRIVATE SECTION.undo IMPORTING levels TYPE integer . DATA: i TYPE integer VALUE 1 . WHEN '-'. newoperator = '+'.my_command TYPE REF TO calculatorcommand Version: 1.command TYPE REF TO calculatorcommand .l_command TYPE REF TO command .redo IMPORTING levels TYPE integer . "constructor METHOD redo. newoperator = '-'. CREATE OBJECT calculator.count TYPE i . ENDMETHOD. ENDCASE. newoperator = ' '. "unexecute METHOD undo. PUBLIC SECTION.current TYPE integer VALUE 0 . CASE operator. WHEN '+'. ENDMETHOD. METHODS: constructor .Project: Design Pattern l_operator = _operator->get( ). newoperator = '*'. "calculatorcommand IMPLEMENTATION *----------------------------------------------------------------------* * CLASS user DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS user DEFINITION. "user DEFINITION *----------------------------------------------------------------------* * CLASS user IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS user IMPLEMENTATION. l_operator = me->undo( l_operator ). WHEN OTHERS.compute IMPORTING operator TYPE char1 operand TYPE integer . ENDMETHOD.0 Side: 166 . "undo ENDCLASS. METHOD constructor. me->calculator->operation( operator = l_operator operand = l_operand ). newoperator = '/'. DATA: calculator TYPE REF TO calculator . ENDCLASS. WHEN '/'. WHEN '*'.commands TYPE TABLE OF REF TO command .

ADD 1 TO i. ENDWHILE. ENDIF. DESCRIBE TABLE commands LINES count. CLASS-DATA: so_application TYPE REF TO lcl_application. WRITE: /. "lcl_application DEFINITION *---------------------------------------------------------* IMPLEMENTATION *---------------------------------------------------------- Version: 1. IF current > 0. ADD 1 TO current. CLASS-METHODS: run./ '----Undo levels '. METHODS: constructor. * perform redo operations WHILE i <= levels.l_command TYPE REF TO command .Project: Design Pattern . levels. SUBTRACT 1 FROM count. my_command ?= l_command. levels. "compute * ENDCLASS.0 Side: 167 . "undo METHOD compute. IF current <= count. WRITE: /. ENDCLASS. DATA: i TYPE integer VALUE 0 . ENDMETHOD. / '----Redo levels '. SUBTRACT 1 FROM current. READ TABLE commands INDEX current INTO l_command . ENDWHILE. PUBLIC SECTION. me->command->execute( ). ENDMETHOD. APPEND me->command TO commands. * perform redo operations WHILE i < levels. ENDIF. my_command ?= l_command. ADD 1 TO current.my_command TYPE REF TO calculatorcommand . ENDMETHOD. "user IMPLEMENTATION *---------------------------------------------------------* CLASS lcl_application DEFINITION *---------------------------------------------------------CLASS lcl_application DEFINITION CREATE PRIVATE. "redo "redo METHOD undo. ADD 1 TO i. READ TABLE commands INDEX current INTO l_command. // Create command operation and execute it CREATE OBJECT command EXPORTING calculator = calculator operator = operator operand = operand. l_command->unexecute( ). l_command->execute( ). PRIVATE SECTION.

"constructor "lcl_application IMPLEMENTATION Report ZDP_COMMAND_REALWORLD Current Current Current Current Value Value Value Value = = = = 100 50 500 250 (following (following (following (following 4 (following (following (following (following + 100 ) . 50 ).exc_text TYPE string. lcl_application=>run( ). "run METHOD constructor.50 ) * 10 ) / 2 ) Undo levels Current Value = Current Value = Current Value = Current Value = Redo levels Current Value = Current Value = Current Value = 500 50 100 0 * 2 / 10 + 50 . user->redo( 3 ). CREATE OBJECT lcl_application=>so_application. 10 ). CATCH cx_sy_create_object_error INTO exc_ref. super->constructor( ). MESSAGE exc_text TYPE 'I'. ENDCLASS. 2 ). exc_text = exc_ref->get_text( ). IF lcl_application=>so_application IS INITIAL. ='+' ='-' ='*' ='/' operand operand operand operand = = = = 100 ). ENDMETHOD. *---------------------------------------------------------METHOD run.100 ) ) ) ) 100 50 500 3 (following + 100 ) (following . TRY. CREATE OBJECT user. DATA: exc_ref TYPE REF TO cx_root . *---------------------------------------------------------* LCL_APPLICATION->RUN(). user->compute( operator user->compute( operator user->compute( operator user->compute( operator user->undo( 4 ). DATA: user TYPE REF TO user.50 ) (following * 10 ) Version: 1. START-OF-SELECTION.0 Side: 168 . ENDIF. ENDTRY. ENDMETHOD.Project: Design Pattern CLASS lcl_application IMPLEMENTATION.

o implements an Interpret operation for nonterminal symbols in the grammar.3 Participants The classes and/or objects participating in this pattern are: • • AbstractExpression (Expression) o declares an interface for executing an operation TerminalExpression ( ThousandExpression.3.0 Side: 169 . The abstract syntax tree is assembled from instances of the NonterminalExpression and TerminalExpression classes o invokes the Interpret operation • • • Version: 1.3 Interpreter A way to include language elements in a program 2..3. NonterminalExpression ( not used ) o one such class is required for every rule R ::= R1R2. Interpret typically calls itself recursively on the variables representing R1 through Rn.Rn in the grammar o maintains instance variables of type AbstractExpression for each of the symbols R1 through Rn.3.1 Definition Given a language.Project: Design Pattern 2. define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language 2. TenExpression.. o an instance is required for every terminal symbol in the sentence.2 UML class diagram 2.3. HundredExpression. OneExpression ) o implements an Interpret operation associated with terminal symbols in the grammar.3.3.3. 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.

Interpreter.3.4 Sample code I C# This structural code demonstrates the Interpreter patterns. // Usually a tree ArrayList list = new ArrayList(). // Interpreter pattern -.Read().0 Side: 170 . using System.Interpret(context). provides the interpreter that processes parsed statements.GangOfFour.Project: Design Pattern 2.3. } // "TerminalExpression" class TerminalExpression : AbstractExpression Version: 1. list. list.Add(new TerminalExpression()).Structural example using System.Collections. } // Wait for user Console. // Populate 'abstract syntax tree' list. which using a defined grammer. list.Add(new TerminalExpression()). } } // "Context" class Context { } // "AbstractExpression" abstract class AbstractExpression { public abstract void Interpret(Context context).Add(new NonterminalExpression()). namespace DoFactory.Add(new TerminalExpression()).Structural { // MainApp test application class MainApp { static void Main() { Context context = new Context(). // Interpret foreach (AbstractExpression exp in list) { exp.

WriteLine("Called Terminal. } } // "NonterminalExpression" class NonterminalExpression : AbstractExpression { public override void Interpret(Context context) { Console.Interpret()"). // Build the 'parse tree' ArrayList tree = new ArrayList(). using System. tree. tree. tree. namespace DoFactory.RealWorld { // MainApp test application class MainApp { static void Main() { string roman = "MCMXXVIII". Context context = new Context(roman).WriteLine("Called Nonterminal.Interpret() Terminal.Collections.Add(new ThousandExpression()).Interpret() Nonterminal.Add(new OneExpression()). } } } Output Called Called Called Called Terminal. tree.Interpret() This real-world code demonstrates the Interpreter pattern which is used to convert a Roman numeral to a decimal.Real World example using System. // Interpreter pattern -. // Interpret foreach (Expression exp in tree) { Version: 1.Project: Design Pattern { public override void Interpret(Context context) { Console.Add(new HundredExpression()).0 Side: 171 .Interpret() Terminal.GangOfFour.Interpret()").Interpreter.Add(new TenExpression()).

context.0 Side: 172 . if (context. context.Input. } } } // "AbstractExpression" abstract class Expression { public void Interpret(Context context) { if (context. } } // "Context" class Context { private string input. } Console.Substring(2). } else if (context.Input = context.Read(). } set{ input = value. private int output.Input.Interpret(context). context. // Wait for user Console.Output += (9 * Multiplier()).Input. Version: 1.WriteLine("{0} = {1}".Output). // Constructor public Context(string input) { this.Input.Length == 0) return. } } public int Output { get{ return output. roman.Input.Input = context.Substring(2).StartsWith(Four())) { context.Output += (4 * Multiplier()). } // Properties public string Input { get{ return input.input = input. } set{ output = value.StartsWith(Nine())) { context.Project: Design Pattern exp.

Substring(1). string Four().Input.StartsWith(Five())) { context. } public override string Nine(){ return "CM".Substring(1). } } Version: 1. CD.Project: Design Pattern } else if (context. } public override string Four(){ return " ". } public override string Five(){ return "L". int Multiplier(). context. } } // Ten checks for X. } public override int Multiplier() { return 1000. } public override string Four(){ return "XL". } public override string Five(){ return " ".Output += (5 * Multiplier()).Input. string Five(). } while (context. . } public override string Four(){ return "CD".0 Side: 173 abstract abstract abstract abstract abstract string One().Input.Output += (1 * Multiplier()).Input = context. } public override int Multiplier() { return 10. } } public public public public public } // Thousand checks for the Roman Numeral M // "TerminalExpression" class ThousandExpression : Expression { public override string One() { return "M". string Nine(). } public override string Nine(){ return "XC".Input. XL.Input = context. } public override int Multiplier() { return 100.StartsWith(One())) { context. } } // Hundred checks C. L and XC // "TerminalExpression" class TenExpression : Expression { public override string One() { return "X". context. } public override string Nine(){ return " ". } public override string Five(){ return "D". D or CM // "TerminalExpression" class HundredExpression : Expression { public override string One() { return "C".

} } } Output MCMXXVIII = 1928 2. VII.4. IX // "TerminalExpression" class OneExpression : Expression { public override string One() { return "I". 2. VI. } public override string Nine(){ return "IX". VI. } public override int Multiplier() { return 1.4 Iterator Sequentially access the elements of a collection 2. V.3.3.Project: Design Pattern // One checks for I.1 Definition Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.3. II.4.4. III.0 Side: 174 . } public override string Five(){ return "V".2 UML class diagram 2. } public override string Four(){ return "IV". IV.3. VIII.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.

a[0] = "Item A". namespace DoFactory.Structural { // MainApp test application class MainApp { static void Main() { ConcreteAggregate a = new ConcreteAggregate().Next(). while (item != null) { Console. // Iterator pattern -.First().Read().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.WriteLine("Iterating over collection:"). // Create Iterator and provide aggregate ConcreteIterator i = new ConcreteIterator(a). Console. o keeps track of the current position in the traversal of the aggregate. a[3] = "Item D".Collections. } } // "Aggregate" abstract class Aggregate Version: 1.3.Structural example using System.4.WriteLine(item).Iterator.GangOfFour. 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. object item = i. item = i. } // Wait for user Console. a[1] = "Item B".0 Side: 175 . using System. a[2] = "Item C".Project: Design Pattern o implements the Iterator interface.

public override Iterator CreateIterator() { return new ConcreteIterator(this).Insert(index.aggregate = aggregate. } // "ConcreteAggregate" class ConcreteAggregate : Aggregate { private ArrayList items = new ArrayList(). } public override object First() { return aggregate[0]. // "ConcreteIterator" class ConcreteIterator : Iterator { private ConcreteAggregate aggregate. } Version: 1. value).0 Side: 176 . // Constructor public ConcreteIterator(ConcreteAggregate aggregate) { this. object CurrentItem().Project: Design Pattern { public abstract Iterator CreateIterator(). } } // Indexer public object this[int index] { get{ return items[index].Count. } } } // "Iterator" abstract { public public public public } class Iterator abstract abstract abstract abstract object First(). object Next(). private int current = 0. bool IsDone(). } // Property public int Count { get{ return items. } set{ items.

Count ? true : false . Version: 1. } public override object CurrentItem() { return aggregate[current]. } } } 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.RealWorld { // MainApp test application class MainApp { static void Main() { // Build a collection Collection collection = new Collection(). collection[4] = new Item("Item 4"). collection[1] = new Item("Item 1").Collections. using System.0 Side: 177 . if (current < aggregate. collection[3] = new Item("Item 3"). collection[2] = new Item("Item 2").1) { ret = aggregate[++current]. namespace DoFactory. } return ret.Project: Design Pattern public override object Next() { object ret = null. // Iterator pattern -.Count .GangOfFour. collection[0] = new Item("Item 0"). } public override bool IsDone() { return current >= aggregate.Iterator.Real World example using System.

First(). Console.Next()) { Console. // Create iterator Iterator iterator = new Iterator(collection). } } } // "Aggregate" interface IAbstractCollection { Iterator CreateIterator().Project: Design Pattern collection[5] collection[6] collection[7] collection[8] = = = = new new new new Item("Item Item("Item Item("Item Item("Item 5").Read(). item = iterator.IsDone.Name).Step = 2. 7"). public Iterator CreateIterator() { Version: 1. for(Item item = iterator. 8"). // Skip every other item iterator. !iterator. } // "ConcreteAggregate" class Collection : IAbstractCollection { private ArrayList items = new ArrayList().0 Side: 178 . } // Property public string Name { get{ return name.WriteLine(item.name = name. } // Wait for user Console. 6").WriteLine("Iterating over collection:"). } } class Item { string name. // Constructor public Item(string name) { this.

} Version: 1.collection = collection.Add(value).Project: Design Pattern return new Iterator(this). } public Item Next() { current += step. if (!IsDone) return collection[current] as Item. } } // "ConcreteIterator" class Iterator : IAbstractIterator { private Collection collection. private int step = 1. } // Property public int Count { get{ return items. else return null. private int current = 0. bool IsDone{ get. } public Item First() { current = 0. Item Next(). } Item CurrentItem{ get. // Constructor public Iterator(Collection collection) { this. } } // Indexer public object this[int index] { get{ return items[index].Count. } } } // "Iterator" interface IAbstractIterator { Item First(). } set{ items. return collection[current] as Item.0 Side: 179 .

} } public bool IsDone { get { return current >= collection.Project: Design Pattern // Properties public int Step { get{ return step.3.Count ? true : false. } set{ step = value. Mediator promotes loose coupling by keeping objects from referring to each other explicitly.5.1 Definition Define an object that encapsulates how a set of objects interact.5 Mediator Defines simplified communication between classes 2. } } } } Output Iterating over collection: Item 0 Item 2 Item 4 Item 6 Item 8 2. and it lets you vary their interaction independently Version: 1.3.0 Side: 180 . } } public Item CurrentItem { get { return collection[current] as Item.

namespace DoFactory.3.Collections. // Mediator pattern -.Mediator. The mediator is a central hub through which all interaction must take place.5. using System.0 Side: 181 .5.4 Sample code I C# This structural code demonstrates the Mediator pattern facilitating loosely coupled communication between different objects and object types.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.Structural { // Mainapp test application class MainApp { static void Main() { ConcreteMediator m = new ConcreteMediator().Structural example using System. Version: 1.5.Project: Design Pattern 2.2 UML class diagram 2.3.GangOfFour.

c2.Notify(message). Colleague colleague). m.0 Side: 182 . c1. } } // "Mediator" abstract class Mediator { public abstract void Send(string message.Read(). thanks"). public ConcreteColleague1 Colleague1 { set{ colleague1 = value.Colleague1 = c1. // Wait for user Console. } else { colleague1. Colleague colleague) { if (colleague == colleague1) { colleague2. } } public override void Send(string message.Send("How are you?"). } // "ConcreteMediator" class ConcreteMediator : Mediator { private ConcreteColleague1 colleague1.Project: Design Pattern ConcreteColleague1 c1 = new ConcreteColleague1(m).Notify(message). } } public ConcreteColleague2 Colleague2 { set{ colleague2 = value.Send("Fine.Colleague2 = c2. ConcreteColleague2 c2 = new ConcreteColleague2(m). } } } // "Colleague" abstract class Colleague Version: 1. private ConcreteColleague2 colleague2. m.

} } // "ConcreteColleague1" class ConcreteColleague1 : Colleague { // Constructor public ConcreteColleague1(Mediator mediator) : base(mediator) { } public void Send(string message) { mediator.Send(message. this).mediator = mediator.WriteLine("Colleague2 gets message: " + message).0 Side: 183 . } public void Notify(string message) { Console. } } } Output Version: 1.WriteLine("Colleague1 gets message: " + message). this). } public void Notify(string message) { Console. // Constructor public Colleague(Mediator mediator) { this.Send(message. } } // "ConcreteColleague2" class ConcreteColleague2 : Colleague { // Constructor public ConcreteColleague2(Mediator mediator) : base(mediator) { } public void Send(string message) { mediator.Project: Design Pattern { protected Mediator mediator.

// Create participants and register them Participant George = new Beatle("George").Send ("Yoko".GangOfFour. Participant Paul = new Beatle("Paul").Send("George".Register(George). } } // "Mediator" abstract class AbstractChatroom Version: 1.RealWorld { // MainApp test application class MainApp { static void Main() { // Create chatroom Chatroom chatroom = new Chatroom(). // Chatting participants Yoko. thanks This real-world code demonstrates the Mediator pattern facilitating loosely coupled communication between different Participants registering with a Chatroom.Register(John). Participant Yoko = new NonBeatle("Yoko"). Participant John = new Beatle("John") . Paul.Read(). "Hi John!").0 Side: 184 . Participant Ringo = new Beatle("Ringo").Register(Ringo).Register(Paul).Send ("John". chatroom. "My sweet Lord"). namespace DoFactory. using System. // Mediator pattern -. Ringo.Send ("Ringo". John. The Chatroom is the central hub through which all communication takes place.Real World example using System.Send ("John".Mediator. chatroom. "My sweet love") . chatroom. At this point only one-toone communication is implemented in the Chatroom. // Wait for user Console. chatroom.Project: Design Pattern Colleague2 gets message: How are you? Colleague1 gets message: Fine.Collections. "Can't buy me love").Register(Yoko). "All you need is love"). Paul. chatroom. but would be trivial to change to oneto-many.

0 Side: 185 . string to. if (pto != null) { pto. } // Properties public string Name { get{ return name.name = name. } participant. public override void Register(Participant participant) { if (participants[participant. } } } // "AbstractColleague" class Participant { private Chatroom chatroom. } } public Chatroom Chatroom { set{ chatroom = value. // Constructor public Participant(string name) { this. private string name. string to. string message). string message) { Participant pto = (Participant)participants[to]. message). } Version: 1.Project: Design Pattern { public abstract void Register(Participant participant). } get{ return chatroom.Chatroom = this. public abstract void Send( string from.Name] = participant. } // "ConcreteMediator" class Chatroom : AbstractChatroom { private Hashtable participants = new Hashtable().Receive(from.Name] == null) { participants[participant. } public override void Send( string from.

Send(name. to.WriteLine("{0} to {1}: '{2}'".Project: Design Pattern } public void Send(string to. string message) { Console.Receive(from.0 Side: 186 . string message) { Console. } } //" ConcreteColleague1" class Beatle : Participant { // Constructor public Beatle(string name) : base(name) { } public override void Receive(string from. message). } } //" ConcreteColleague2" class NonBeatle : Participant { // Constructor public NonBeatle(string name) : base(name) { } public override void Receive(string from. string message) { chatroom. message). base.Receive(from. from. string message) { Console. } public virtual void Receive( string from. base. Name. message). } } } Output To To To To To a a a a a Beatle: Yoko to John: 'Hi John!' Beatle: Paul to Ringo: 'All you need is love' Beatle: Ringo to George: 'My sweet Lord' Beatle: Paul to John: 'Can't buy me love' non-Beatle: John to Yoko: 'My sweet love' Version: 1.Write("To a non-Beatle: "). message).Write("To a Beatle: ").

// Memento pattern -.Structural example using System. 2.3. capture and externalize an object's internal state so that the object can be restored to this state later.6 Memento Capture and restore an object's internal state 2.6. in contrast. Caretaker sees a narrow interface to the Memento -.3.Structural { Version: 1. Mementos have effectively two interfaces. • • 2.it can only pass the memento to the other objects.6. Ideally.0 Side: 187 . namespace DoFactory.3.3. only the originator that produces the memento would be permitted to access the memento's internal state. The memento may store as much or as little of the originator's internal state as necessary at its originator's discretion.GangOfFour. Originator (SalesProspect) o creates a memento containing a snapshot of its current internal state. o protect against access by objects of other than the originator.2 UML class diagram 2.4 Sample code I C# This structural code demonstrates the Memento pattern which temporary saves and restores another object's internal state.3 Participants The classes and/or objects participating in this pattern are: • Memento (Memento) o stores internal state of the Originator object. one that lets it access all the data necessary to restore itself to its previous state. sees a wide interface.6. 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. Originator.Memento.Project: Design Pattern 2.1 Definition Without violating encapsulation.3.6.

} set { state = value.CreateMemento().WriteLine("State = " + state).SetMemento(c. } } // "Memento" Version: 1. // Continue changing originator o. // Store internal state Caretaker c = new Caretaker(). // Property public string State { get{ return state.State = "On". } public void SetMemento(Memento memento) { Console.Read(). } } // "Originator" class Originator { private string state. // Restore saved state o. o. Console.Memento = o.State. c.Memento). } } public Memento CreateMemento() { return (new Memento(state)).WriteLine("Restoring state:"). // Wait for user Console.0 Side: 188 . State = memento.Project: Design Pattern // MainApp test application class MainApp { static void Main() { Originator o = new Originator().State = "Off".

Version: 1. namespace DoFactory.GangOfFour. } } } // "Caretaker" class Caretaker { private Memento memento. } // Property public string State { get{ return state.Memento. // Constructor public Memento(string state) { this.RealWorld { // MainApp test application class MainApp { static void Main() { SalesProspect s = new SalesProspect(). } get{ return memento.Real World example using System. // Property public Memento Memento { set{ memento = value. // Memento pattern -.0 Side: 189 .Project: Design Pattern class Memento { private string state. } } } } 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.state = state.

// Restore saved state s.RestoreMemento(m.WriteLine("Phone: " + phone).Name = "Leo Welch". // Properties public string Name { get{ return name.Read(). } set { phone = value. } set { budget = value.Phone = "(412) 256-0990".0 Side: 190 . } } // "Originator" class SalesProspect { private string name.Phone = "(310) 209-7111". s. } } public string Phone { get{ return phone.Project: Design Pattern s.SaveMemento(). Console. private string phone. s.0.Name = "Noel van Halen". m. // Continue changing originator s.0. // Store internal state ProspectMemory m = new ProspectMemory().Budget = 25000.WriteLine("Name: " + name). private double budget. s. } set { name = value.Memento = s. Version: 1.Budget = 1000000. // Wait for user Console. s. Console.Memento). } } public double Budget { get{ return budget.

} set{ phone = value.0 Side: 191 . } public void RestoreMemento(Memento memento) { Console. } } public string Phone { get{ return phone. // Constructor public Memento(string name. this. } } } // "Caretaker" Version: 1. } } public Memento SaveMemento() { Console. this.Project: Design Pattern Console.Phone = memento. double budget) { this. this. } } // "Memento" class Memento { private string name. } set{ budget = value. private double budget.Name = memento. string phone.WriteLine("Budget: " + budget). } // Properties public string Name { get{ return name. } set{ name = value.phone = phone. private string phone. budget).name = name. } } public double Budget { get{ return budget. this. return new Memento(name.budget = budget.WriteLine("\nSaving state --\n").Phone.Name. this.Budget = memento. phone.Budget.WriteLine("\nRestoring state --\n").

// Property public Memento Memento { set{ memento = value. all its dependents are notified and updated automatically.Project: Design Pattern class ProspectMemory { private Memento memento.0 Side: 192 .1 Definition Define a one-to-many dependency between objects so that when one object changes state.7.3.3. } } } } 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. Version: 1. } get{ return memento.7 Observer A way of notifying change to a number of classes 2.

3.Observer.GangOfFour. namespace DoFactory.Structural example using System.Project: Design Pattern 2. using System. 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. Any number of Observer objects may observe a subject o provides an interface for attaching and detaching Observer objects. // Observer pattern -.0 Side: 193 .7.7. 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.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.3.3.Collections.7.Structural { Version: 1.2 UML class diagram 2.3 Participants The classes and/or objects participating in this pattern are: • Subject (Stock) o knows its observers.

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 ibm.Price ibm.Price ibm.Price ibm.Price price, which notifies investors = 120.10; = 121.00; = 120.50; = 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.Symbol. stock.10 Notified Sorros of IBM's change to $121.1 Definition Allow an object to alter its behavior when its internal state changes. } public void Update(Stock stock) { Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}".50 Notified Berkshire of IBM's change to $120.3.0 Side: 198 .2 UML class diagram Version: 1.Price). name.8 State Alter an object's behavior when its state changes 2.00 Notified Berkshire of IBM's change to $121. } // Property public Stock Stock { get{ return stock.3.name = name. } set{ stock = value. The object will appear to change its class 2.00 Notified Sorros of IBM's change to $120.10 Notified Berkshire of IBM's change to $120. } } } } Output Notified Sorros of IBM's change to $120.50 Notified Sorros of IBM's change to $120.75 Notified Berkshire of IBM's change to $120.8.3. stock.8.75 2.

Version: 1.3. c. namespace DoFactory.8.GangOfFour.8.Read().4 Sample code I C# This structural code demonstrates the State pattern which allows an object to behave differently depending on its internal state.Structural { // MainApp test application class MainApp { static void Main() { // Setup context in a state Context c = new Context(new ConcreteStateA()). which toggles state c.Request().0 Side: 199 .Request().Request().Structural example using System.Request(). c.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. SilverState.3. Concrete State (RedState.State. State (State) o defines an interface for encapsulating the behavior associated with a particular state of the Context. } } // "State" abstract class State { public abstract void Handle(Context context). The difference in behavior is delegated to objects that represent this state. // State pattern -. // Issue requests.Project: Design Pattern 2. // Wait for user Console. c. GoldState) o each subclass implements a behavior associated with a state of Context • • 2.

Project: Design Pattern } // "ConcreteStateA" class ConcreteStateA : State { public override void Handle(Context context) { context. Console. } } } Output State: ConcreteStateA State: ConcreteStateB State: ConcreteStateA Version: 1.State = new ConcreteStateB(). } } // "ConcreteStateB" class ConcreteStateB : State { public override void Handle(Context context) { context.State = state. } } public void Request() { state. } // Property public State State { get{ return state.Handle(this).WriteLine("State: " + state.0 Side: 200 . } set { state = value.GetType(). // Constructor public Context(State state) { this.Name).State = new ConcreteStateA(). } } // "Context" class Context { private State state.

Deposit(550. // Properties public Account Account { get{ return account. SilverState and GoldState.Deposit(500.Real World example using System. account.Deposit(300. namespace DoFactory. starter accounts. account. The difference in behavior is delegated to State objects called RedState.0 Side: 201 .Read(). } set{ account = value.PayInterest(). account. protected double upperLimit. account. protected double balance.Withdraw(2000. protected double interest.00). protected double lowerLimit.00).State. } } Version: 1.0).RealWorld { // MainApp test application class MainApp { static void Main() { // Open a new account Account account = new Account("Jim Johnson").GangOfFour. account. These states represent overdrawn accounts. and accounts in good standing. // Wait for user Console.0).Withdraw(1100. // State pattern -. // Apply financial transactions account. } } // "State" abstract class State { protected Account account.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.0).

StateChangeCheck(). public abstract void PayInterest(). } // "ConcreteState" // Account is overdrawn class RedState : State { double serviceFee. } public override void Withdraw(double amount) { amount = amount . } private void Initialize() { // Should come from a datasource interest = 0. Initialize(). serviceFee = 15.Balance. upperLimit = 0.Project: Design Pattern public double Balance { get{ return balance. } } public abstract void Deposit(double amount).WriteLine("No funds available for withdrawal!").0.0. // Constructor public RedState(State state) { this.0. public abstract void Withdraw(double amount).balance = state.account = state.00.serviceFee. } public override void PayInterest() { // No interest is paid } private void StateChangeCheck() { if (balance > upperLimit) Version: 1. } public override void Deposit(double amount) { balance += amount. this. lowerLimit = -100. Console.0 Side: 202 .Account. } set{ balance = value.

0. StateChangeCheck().Balance.0 Side: 203 . } public override void Withdraw(double amount) { balance -= amount.State = new SilverState(this). StateChangeCheck(). this. Initialize(). } private void Initialize() { // Should come from a datasource interest = 0. } private void StateChangeCheck() { if (balance < lowerLimit) { Version: 1.Account) { } public SilverState(double balance.0.balance = balance. StateChangeCheck().Project: Design Pattern { account.account = account. } public override void Deposit(double amount) { balance += amount. upperLimit = 1000. lowerLimit = 0.0. } public override void PayInterest() { balance += interest * balance. Account account) { this. } } } // "ConcreteState" // Silver is non-interest bearing state class SilverState : State { // Overloaded constructors public SilverState(State state) : this( state. state.

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

ContextInterface(). } } // "Context" class Context { Strategy strategy. } // "ConcreteStrategyA" class ConcreteStrategyA : Strategy { public override void AlgorithmInterface() { Console.AlgorithmInterface()").0 Side: 208 . } } // "ConcreteStrategyB" class ConcreteStrategyB : Strategy { public override void AlgorithmInterface() { Console.AlgorithmInterface()").AlgorithmInterface()").Project: Design Pattern context = new Context(new ConcreteStrategyB()).WriteLine( "Called ConcreteStrategyB. context = new Context(new ConcreteStrategyC()).Read(). } } // "Strategy" abstract class Strategy { public abstract void AlgorithmInterface(). // Wait for user Console.ContextInterface(). context. } } // "ConcreteStrategyC" class ConcreteStrategyC : Strategy { public override void AlgorithmInterface() { Console.WriteLine( "Called ConcreteStrategyA. context.WriteLine( "Called ConcreteStrategyC. Version: 1.

studentRecords.Collections. and Mergesort. studentRecords.AlgorithmInterface().Strategy.Sort().AlgorithmInterface() Called ConcreteStrategyC.Add("Sandra").strategy = strategy.AlgorithmInterface() Called ConcreteStrategyB.SetSortStrategy(new QuickSort()). using System.RealWorld { // MainApp test application class MainApp { static void Main() { // Two contexts following different strategies SortedList studentRecords = new SortedList(). studentRecords. studentRecords.Sort(). studentRecords. } public void ContextInterface() { strategy.Add("Vivek"). studentRecords.0 Side: 209 .SetSortStrategy(new ShellSort()). studentRecords. studentRecords. namespace DoFactory.Real World example using System. studentRecords.Sort().GangOfFour. Version: 1. // Strategy pattern -. studentRecords. studentRecords.Project: Design Pattern // Constructor public Context(Strategy strategy) { this.Add("Anna").Add("Jimmy"). This allows clients to dynamically change sorting strategies including Quicksort. Shellsort. } } } Output Called ConcreteStrategyA.Add("Samual").AlgorithmInterface() This real-world code demonstrates the Strategy pattern which encapsulates sorting algorithms in the form of sorting objects.SetSortStrategy(new MergeSort()).

} Version: 1. } } // "Context" class SortedList { private ArrayList list = new ArrayList().MergeSort(). public void SetSortStrategy(SortStrategy sortstrategy) { this.ShellSort(). } // "ConcreteStrategy" class QuickSort : SortStrategy { public override void Sort(ArrayList list) { list.Project: Design Pattern // Wait for user Console.WriteLine("MergeSorted list "). } } // "ConcreteStrategy" class ShellSort : SortStrategy { public override void Sort(ArrayList list) { //list. not-implemented Console.Sort(). private SortStrategy sortstrategy.WriteLine("QuickSorted list "). } } // "ConcreteStrategy" class MergeSort : SortStrategy { public override void Sort(ArrayList list) { //list. not-implemented Console. } } // "Strategy" abstract class SortStrategy { public abstract void Sort(ArrayList list).WriteLine("ShellSorted list ").0 Side: 210 .Read(). // Default is Quicksort Console.sortstrategy = sortstrategy.

10 Template Method Defer the exact steps of an algorithm to a subclass 2. } } } Output QuickSorted list Anna Jimmy Samual Sandra Vivek ShellSorted list Anna Jimmy Samual Sandra Vivek MergeSorted list Anna Jimmy Samual Sandra Vivek 2.3.WriteLine(" " + name).Sort(list). deferring some steps to subclasses.Project: Design Pattern public void Add(string name) { list.Add(name).10. } public void Sort() { sortstrategy. } Console. // Display results foreach (string name in list) { Console.1 Definition Define the skeleton of an algorithm in an operation.0 Side: 211 .WriteLine().3. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure Version: 1.

0 Side: 212 . The template method calls primitive operations as well as operations defined in AbstractClass or those of other objects.3.Project: Design Pattern 2.2 UML class diagram 2.3.Structural { // MainApp test application class MainApp { static void Main() { AbstractClass c.4 Sample code In C# This structural code demonstrates the Template method which provides a skeleton calling sequence of methods.3.Structural example using System. Version: 1.10. ConcreteClass (CustomerDataObject) o implements the primitive operations ot carry out subclass-specific steps of the algorithm • 2.Template.GangOfFour.10. namespace DoFactory. // Template pattern -.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. One or more steps can be deferred to subclasses which implement these steps without changing the overall calling sequence.

} } // "AbstractClass" abstract class AbstractClass { public abstract void PrimitiveOperation1().PrimitiveOperation2()").TemplateMethod(). } public override void PrimitiveOperation2() { Console. } } // "ConcreteClass" class ConcreteClassA : AbstractClass { public override void PrimitiveOperation1() { Console. public abstract void PrimitiveOperation2().PrimitiveOperation2()"). PrimitiveOperation2(). } public override void PrimitiveOperation2() { Console.WriteLine("ConcreteClassA.TemplateMethod().WriteLine("ConcreteClassB. c. c.WriteLine(""). Console. } } } Output Version: 1.Project: Design Pattern c = new ConcreteClassA().WriteLine("ConcreteClassB. c = new ConcreteClassB().PrimitiveOperation1()"). // Wait for user Console. } } class ConcreteClassB : AbstractClass { public override void PrimitiveOperation1() { Console. // The "Template method" public void TemplateMethod() { PrimitiveOperation1().0 Side: 213 .PrimitiveOperation1()").Read().WriteLine("ConcreteClassA.

OLEDB. // Template pattern -. dao. Implementation of these steps are deferred to the CustomerDataObject subclass which implements the Connect. " + "data source=c:\\nwind.Data. using System. dao = new Products(). // Wait for user Console. protected DataSet dataSet.PrimitiveOperation1() ConcreteClassA. Select.Run().OleDb.RealWorld { // MainApp test application class MainApp { static void Main() { DataAccessObject dao.Real World example using System.GangOfFour. dao = new Categories().JET. Process.PrimitiveOperation2() This real-world code demonstrates a Template method named Run() which provides a skeleton calling sequence of methods. } } // "AbstractClass" abstract class DataAccessObject { protected string connectionString.mdb".Template.Data.4.0 Side: 214 .Project: Design Pattern ConcreteClassA.0. using System. public virtual void Disconnect() Version: 1.Read().Run(). public virtual void Connect() { // Make sure mdb is on c:\ connectionString = "provider=Microsoft. dao. and Disconnect methods. namespace DoFactory. } public abstract void Select(). public abstract void Process().

connectionString). "Categories"). } public override void Process() { Console. Process(). DataTable dataTable = dataSet. dataAdapter.Rows) { Console. dataSet = new DataSet(). } public override void Process() { Version: 1. OleDbDataAdapter dataAdapter = new OleDbDataAdapter( sql. } // The "Template Method" public void Run() { Connect(). } } // "ConcreteClass" class Categories : DataAccessObject { public override void Select() { string sql = "select CategoryName from Categories". OleDbDataAdapter dataAdapter = new OleDbDataAdapter( sql.Project: Design Pattern { connectionString = "".Tables["Categories"]. connectionString).Fill(dataSet. } } class Products : DataAccessObject { public override void Select() { string sql = "select ProductName from Products". Select(). Disconnect().WriteLine(row["CategoryName"])."). dataSet = new DataSet().WriteLine("Categories ---. } Console. foreach (DataRow row in dataTable.Fill(dataSet. "Products").WriteLine().0 Side: 215 . dataAdapter.

WriteLine(row["ProductName"]).11. } } } 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. foreach (DataRow row in dataTable.Rows) { Console. Version: 1.Tables["Products"]. Visitor lets you define a new operation without changing the classes of the elements on which it operates.").3.Project: Design Pattern Console. } Console.WriteLine().0 Side: 216 .3.WriteLine("Products ---.1 Definition Represent an operation to be performed on the elements of an object structure.11 Visitor Defines a new operation to a class without change 2. DataTable dataTable = dataSet.

11.11. The operation's name and signature identifies the class that sends the Visit request to the visitor.2 UML class diagram 2. Then the visitor can access the elements directly through its particular interface ConcreteVisitor (IncomeVisitor.3.Project: Design Pattern 2. Each operation implements a fragment of the algorithm defined for the corresponding class or object in the structure. ConcreteElement (Employee) • • • Version: 1. Element (Element) o defines an Accept operation that takes a visitor as an argument. VacationVisitor) o implements each operation declared by Visitor. This state often accumulates results during the traversal of the structure.0 Side: 217 . ConcreteVisitor provides the context for the algorithm and stores its local state.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.3. That lets the visitor determine the concrete class of the element being visited.

Accept(v1).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. // Create visitor objects ConcreteVisitor1 v1 = new ConcreteVisitor1(). namespace DoFactory. Different visitor objects define different operations.Accept(v2). o.Visitor. public abstract void VisitConcreteElementB( ConcreteElementB concreteElementB).11. o.Collections.Structural example using System. ConcreteVisitor2 v2 = new ConcreteVisitor2(). o.Read().0 Side: 218 . // Wait for user Console.Attach(new ConcreteElementB()).3.Attach(new ConcreteElementA()). } Version: 1. // Visitor pattern -.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. using System.GangOfFour. // Structure accepting visitors o. } } // "Visitor" abstract class Visitor { public abstract void VisitConcreteElementA( ConcreteElementA concreteElementA).Structural { // MainApp test application class MainApp { static void Main() { // Setup structure ObjectStructure o = new ObjectStructure().

concreteElementB.GetType(). this. this.WriteLine("{0} visited by {1}".Name).Name). } } // "ConcreteVisitor2" class ConcreteVisitor2 : Visitor { public override void VisitConcreteElementA( ConcreteElementA concreteElementA) { Console.WriteLine("{0} visited by {1}".WriteLine("{0} visited by {1}".GetType().GetType().Name).WriteLine("{0} visited by {1}". } public override void VisitConcreteElementB( ConcreteElementB concreteElementB) { Console. concreteElementA.0 Side: 219 . } public override void VisitConcreteElementB( ConcreteElementB concreteElementB) { Console.Name). } public void OperationA() { Version: 1.Name. } // "ConcreteElementA" class ConcreteElementA : Element { public override void Accept(Visitor visitor) { visitor. this.Project: Design Pattern // "ConcreteVisitor1" class ConcreteVisitor1 : Visitor { public override void VisitConcreteElementA( ConcreteElementA concreteElementA) { Console.GetType().Name.GetType(). concreteElementB.Name.GetType().Name. concreteElementA.VisitConcreteElementA(this).GetType(). } } // "Element" abstract class Element { public abstract void Accept(Visitor visitor).GetType(). this.

Real World example Version: 1. } public void Detach(Element element) { elements. } public void Accept(Visitor visitor) { foreach (Element e in elements) { e. } } } } Output ConcreteElementA ConcreteElementB ConcreteElementA ConcreteElementB visited visited visited visited by by by by ConcreteVisitor1 ConcreteVisitor1 ConcreteVisitor2 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.Remove(element). // Visitor pattern -.one adjusts vacation days and the other income.VisitConcreteElementB(this).0 Side: 220 .Project: Design Pattern } } // "ConcreteElementB" class ConcreteElementB : Element { public override void Accept(Visitor visitor) { visitor. The two visitor objects define different operations -.Add(element). public void Attach(Element element) { elements. } public void OperationB() { } } // "ObjectStructure" class ObjectStructure { private ArrayList elements = new ArrayList().Accept(visitor).

// Wait for user Console. } } // "ConcreteVisitor2" class VacationVisitor : IVisitor { public void Visit(Element element) Version: 1. // Employees are 'visited' e.Name.GangOfFour. } // "ConcreteVisitor1" class IncomeVisitor : IVisitor { public void Visit(Element element) { Employee employee = element as Employee. } } // "Visitor" interface IVisitor { void Visit(Element element).Name. // Provide 10% pay raise employee.Income *= 1.Visitor.GetType(). e.0 Side: 221 .Read().RealWorld { // MainApp startup application class MainApp { static void Main() { // Setup employee collection Employees e = new Employees(). using System.Attach(new President()).Attach(new Clerk()). employee.Attach(new Director()).Accept(new IncomeVisitor()).Accept(new VacationVisitor()). e. employee.Income). employee.Project: Design Pattern using System. e. e. namespace DoFactory.Collections. Console.WriteLine("{0} {1}'s new income: {2:C}".10.

Version: 1. 14) { } } class Director : Employee { // Constructor public Director() : base("Elly". 35000. } // "ConcreteElement" class Employee : Element { string name. employee. } } class Clerk : Employee { // Constructor public Clerk() : base("Hank". 25000. int vacationDays) { this. // Provide 3 extra vacation days Console.0 Side: 222 .Name. double income.0.GetType().Name. double income.name = name. employee. int vacationDays.vacationDays = vacationDays. // Constructor public Employee(string name.Project: Design Pattern { Employee employee = element as Employee.0. 21) { } } // "Element" abstract class Element { public abstract void Accept(IVisitor visitor). employee.0. 16) { } } class President : Employee { // Constructor public President() : base("Dick".income = income. this.WriteLine("{0} {1}'s new vacation days: {2}". this.VacationDays). 45000.

} set{ name = value. } Console. } } public override void Accept(IVisitor visitor) { visitor. } set{ vacationDays = value. } } public int VacationDays { get{ return vacationDays. } public void Detach(Employee employee) { employees. } } // "ObjectStructure" class Employees { private ArrayList employees = new ArrayList().Add(employee). } } } Output Version: 1.WriteLine().Visit(this). } public void Accept(IVisitor visitor) { foreach (Employee e in employees) { e. public void Attach(Employee employee) { employees.Project: Design Pattern } // Properties public string Name { get{ return name. } } public double Income { get{ return income.Accept(visitor).Remove(employee).0 Side: 223 . } set{ income = value.

500.0 Side: 224 .500.Project: Design Pattern Clerk Hank's new income: $27.00 President Dick's new income: $49.00 Clerk Hank's new vacation days: 14 Director Elly's new vacation days: 16 President Dick's new vacation days: 21 Version: 1.00 Director Elly's new income: $38.500.

Sign up to vote on this title
UsefulNot useful