Professional Documents
Culture Documents
Design Patterns: Implementation of Objects Using Design Patterns in Abap Object
Design Patterns: Implementation of Objects Using Design Patterns in Abap Object
Version: 1
Date: 2. Januar 2008
Project: Design Pattern
Version management
Date What has changed Sections Whom Version
01.12.2007 Creation of the document All BGS 1.0
Reference documents
Document Version Location
The Gang Of Four
Participants
Name Company Roll in the project
Benny G. Sørensen BGS
Consulting
ApS
Version: 1.0
Side: ii
Project: Design Pattern
Contents:
1 INTRODUCTION 6
2 DESIGN PATTERNS 6
2.1 CREATIONAL PATTERNS 7
2.1.1 Abstract Factory 7
2.1.1.1 Definition 7
2.1.1.2 Commen Use 8
2.1.1.3 UML class diagram 10
2.1.1.4 Participants 10
2.1.1.5 Sample code in C# 10
2.1.1.6 Sample code in ABAP 13
2.1.1.7 Sample code in C# 16
2.1.1.8 Sample code in ABAP 18
2.1.2 Builder 21
2.1.2.1 Definition 21
2.1.2.2 Useful tips 21
2.1.2.3 UML class diagram 22
2.1.2.4 Participants 22
2.1.2.5 Sample code In C# 22
2.1.2.6 Sample code In ABAP 25
2.1.2.7 Sample code In C# 27
2.1.2.8 Sample code In ABAP 31
2.1.3 Factory Method 34
2.1.3.1 Definition 34
2.1.3.2 UML class diagram 35
2.1.3.3 Participants 35
2.1.3.4 Sample code In C# 35
2.1.3.5 Sample code in ABAP 40
2.1.3.6 Sample code in ABAP 42
2.1.3.7 Sample code in ABAP 44
2.1.4 Prototype 47
2.1.4.1 Definition 47
2.1.4.2 Used for 47
2.1.4.3 UML class diagram 48
2.1.4.4 Participants 48
2.1.4.5 Sample code In C# 48
2.1.4.6 Sample code In ABAP 50
2.1.4.7 Sample code In C# 52
2.1.4.8 Sample code In ABAP 54
2.1.5 Singleton 57
2.1.5.1 Definition 57
2.1.5.2 Common Use 57
2.1.5.3 Implementation 58
2.1.5.4 UML class diagram 59
2.1.5.5 Participants 59
2.1.5.6 Sample code In C# 59
2.1.5.7 Sample code In ABAP 60
2.1.5.8 Sample code In C# 62
2.1.5.9 Sample code In ABAP 64
2.1.5.10 Sample code In ABAP for Application 66
2.2 STRUCTURAL PATTERNS 67
2.2.1 Adapter 67
2.2.1.1 Definition 67
2.2.1.2 Common Use 68
2.2.1.3 UML class diagram 69
2.2.1.4 Participants 69
Version: 1.0
Side: 3
Project: Design Pattern
Version: 1.0
Side: 4
Project: Design Pattern
Version: 1.0
Side: 5
Project: Design Pattern
1 Introduction
2 Design Patterns
Design patterns are recurring solutions to software design problems you find
again and again in real-world application development. Patterns are about
design and interaction of objects, as well as providing a communication
platform concerning elegant, reusable solutions to commonly encountered
programming challenges.
These design patterns have been copied from The Gang of Four homepage.
The Gang of Four (GoF) patterns are generally considered the foundation for all
other patterns. They are categorized in three groups: Creational, Structural,
and Behavioral. Here you will find information on these important patterns.
Structural code uses type names as defined in the pattern definition and UML
diagrams.
A third form, 'ABAP Object' demonstrates design patterns that exploit SAP R/3
built-in ABAP Object’s features.
Creational Patterns
Structural Patterns
Version: 1.0
Side: 6
Project: Design Pattern
Behavioral Patterns
2.1.1.1 Definition
Provide an interface for creating families of related or dependent objects
without specifying their concrete classes
The client does not know (nor care) about which concrete objects it gets from
each of these internal factories since it uses only the generic interfaces of their
products. This pattern separates the details of implementation of a set of
objects from its general usage.
Version: 1.0
Side: 7
Project: Design Pattern
The system would have any number of derived concrete versions of the
DocumentCreator class like FancyDocumentCreator or
ModernDocumentCreator, each with a different implementation of
createLetter() and createResume() that would create a corresponding object
like FancyLetter or ModernResume. Each of these products is derived from a
simple abstract class like Letter or Resume of which the client is aware. The
client code would get an appropriate instantiation of the DocumentCreator and
call its factory methods. Each of the resulting objects would be created from
the same DocumentCreator implementation and would share a common theme
(they would all be fancy or modern objects). The client would need to know
how to handle only the abstract Letter or Resume class, not the specific
version that it got from the concrete factory.
The factory determines the actual concrete type of object to be created, and it
is here that the object is actually created (in C++, for instance, by the new
operator). However, the factory only returns an abstract pointer to the created
concrete object.
This insulates client code from object creation by having clients ask a factory
object to create an object of the desired abstract type and to return an
abstract pointer to the object.
As the factory only returns an abstract pointer, the client code (which
requested the object from the factory) does not know - and is not burdened by
- the actual concrete type of the object which was just created. However, the
type of a concrete object (and hence a concrete factory) is known by the
abstract factory; for instance, the factory may read it from a configuration file.
The client has no need to specify the type, since it has already been specified
in the configuration file. In particular, this means:
Version: 1.0
Side: 8
Project: Design Pattern
• The client code has no knowledge whatsoever of the concrete type, not
needing to include any header files or class declarations relating to the
concrete type. The client code deals only with the abstract type. Objects
of a concrete type are indeed created by the factory, but the client code
accesses such objects only through their abstract interface.
• Adding new concrete types is done by modifying the client code to use a
different factory, a modification which is typically one line in one file.
(The different factory then creates objects of a different concrete type,
but still returns a pointer of the same abstract type as before - thus
insulating the client code from change.) This is significantly easier than
modifying the client code to instantiate a new type, which would require
changing every location in the code where a new object is created (as
well as making sure that all such code locations also have knowledge of
the new concrete type, by including for instance a concrete class header
file). If all factory objects are stored globally in a singleton object, and all
client code goes through the singleton to access the proper factory for
object creation, then changing factories is as easy as changing the
singleton object.
Version: 1.0
Side: 9
Project: Design Pattern
2.1.1.4 Participants
The classes and/or objects participating in this pattern are:
• AbstractFactory (ContinentFactory)
declares an interface for operations that create abstract products
• ConcreteFactory (AfricaFactory, AmericaFactory)
implements the operations to create concrete product objects
• AbstractProduct (Herbivore, Carnivore)
declares an interface for a type of product object
• Product (Wildebeest, Lion, Bison, Wolf)
defines a product object to be created by the corresponding concrete
factory implements the AbstractProduct interface
• Client (AnimalWorld)
uses interfaces declared by AbstractFactory and AbstractProduct classes
Version: 1.0
Side: 10
Project: Design Pattern
using System;
namespace DoFactory.GangOfFour.Abstract.Structural
{
// MainApp test application
class MainApp
{
public static void Main()
{
// Abstract factory #1
AbstractFactory factory1 = new ConcreteFactory1();
Client c1 = new Client(factory1);
c1.Run();
// Abstract factory #2
AbstractFactory factory2 = new ConcreteFactory2();
Client c2 = new Client(factory2);
c2.Run();
// "AbstractFactory"
// "ConcreteFactory1"
// "ConcreteFactory2"
Version: 1.0
Side: 11
Project: Design Pattern
{
return new ProductB2();
}
}
// "AbstractProductA"
// "AbstractProductB"
// "ProductA1"
// "ProductB1"
// "ProductA2"
// "ProductB2"
class Client
{
Version: 1.0
Side: 12
Project: Design Pattern
// Constructor
public Client(AbstractFactory factory)
{
AbstractProductB = factory.CreateProductB();
AbstractProductA = factory.CreateProductA();
}
Output
ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
Version: 1.0
Side: 13
Project: Design Pattern
PUBLIC SECTION.
METHODS:
interact REDEFINITION.
ENDCLASS. "productb1 DEFINITION
METHOD createproductb.
CREATE OBJECT productb TYPE productb1.
ENDMETHOD. "createproductb
ENDCLASS. "concretefactory1 IMPLEMENTATION
Version: 1.0
Side: 14
Project: Design Pattern
METHODS:
createproducta REDEFINITION
,createproductb REDEFINITION
.
ENDCLASS. "concretefactory2 DEFINITION
METHOD createproductb.
CREATE OBJECT productb TYPE productb2.
ENDMETHOD. "createproductb
ENDCLASS. "concretefactory1 IMPLEMENTATION
ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Version: 1.0
Side: 15
Project: Design Pattern
Output
PRODUCTB1
Interact with
PRODUCTA1
PRODUCTB2
Interact with
PRODUCTA2
using System;
namespace DoFactory.GangOfFour.Abstract.RealWorld
{
// MainApp test application
class MainApp
{
public static void Main()
{
// Create and run the Africa animal world
ContinentFactory africa = new AfricaFactory();
AnimalWorld world = new AnimalWorld(africa);
world.RunFoodChain();
// "AbstractFactory"
// "ConcreteFactory1"
Version: 1.0
Side: 16
Project: Design Pattern
// "ConcreteFactory2"
// "AbstractProductA"
// "AbstractProductB"
// "ProductA1"
// "ProductB1"
// "ProductA2"
Version: 1.0
Side: 17
Project: Design Pattern
{
}
// "ProductB2"
// "Client"
class AnimalWorld
{
private Herbivore herbivore;
private Carnivore carnivore;
// Constructor
public AnimalWorld(ContinentFactory factory)
{
carnivore = factory.CreateCarnivore();
herbivore = factory.CreateHerbivore();
}
Output
Lion eats Wildebeest
Wolf eats Bison
DEFINE ?get_class_name.
Version: 1.0
Side: 18
Project: Design Pattern
Version: 1.0
Side: 19
Project: Design Pattern
METHOD createcarnivore.
CREATE OBJECT carnivore TYPE lion.
ENDMETHOD. "createproductb
ENDCLASS. "ContinentFactory IMPLEMENTATION
METHOD createcarnivore.
CREATE OBJECT carnivore TYPE wolf.
ENDMETHOD. "createproductb
ENDCLASS. "ContinentFactory IMPLEMENTATION
Version: 1.0
Side: 20
Project: Design Pattern
ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Output
LION
eats
WILDEBEEST
WOLF
eats
BISON
2.1.2 Builder
Separates object construction from its representation
2.1.2.1 Definition
Separate the construction of a complex object from its representation so that
the same construction process can create different representations.
Version: 1.0
Side: 21
Project: Design Pattern
• Often, designs start out using Factory Method (less complicated, more
customizable, subclasses proliferate) and evolve toward Abstract Factory,
Prototype, or Builder (more flexible, more complex) as the designer
discovers where more flexibility is needed.
2.1.2.4 Participants
The classes and/or objects participating in this pattern are:
• Builder (VehicleBuilder)
o specifies an abstract interface for creating parts of a Product object
• ConcreteBuilder (MotorCycleBuilder, CarBuilder, ScooterBuilder)
o constructs and assembles parts of the product by implementing the
Builder interface defines and keeps track of the representation it
creates provides an interface for retrieving the product
• Director (Shop)
o constructs an object using the Builder interface
• Product (Vehicle)
o represents the complex object under construction. ConcreteBuilder
builds the product's internal representation and defines the process
by which it's assembled includes classes that define the constituent
parts, including interfaces for assembling the parts into the final
result
Version: 1.0
Side: 22
Project: Design Pattern
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Builder.Structural
{
// MainApp test application
director.Construct(b2);
Product p2 = b2.GetResult();
p2.Show();
// "Director"
class Director
{
// Builder uses a complex series of steps
public void Construct(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
}
// "Builder"
// "ConcreteBuilder1"
Version: 1.0
Side: 23
Project: Design Pattern
{
private Product product = new Product();
// "ConcreteBuilder2"
// "Product"
class Product
{
ArrayList parts = new ArrayList();
Version: 1.0
Side: 24
Project: Design Pattern
Console.WriteLine(part);
}
}
}
Output
Product Parts -------
PartA
PartB
METHOD show.
DATA: parts_line TYPE string.
WRITE: / 'Product Parts --------'.
LOOP AT parts INTO parts_line.
WRITE: / parts_line.
ENDLOOP.
ENDMETHOD. "show
ENDCLASS. "product IMPLEMENTATION
Version: 1.0
Side: 25
Project: Design Pattern
.
PRIVATE SECTION.
DATA: product TYPE REF TO product.
ENDCLASS. "concretebuilder1 DEFINITION
Version: 1.0
Side: 26
Project: Design Pattern
ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Output
Product Parts
PartA
Partb
Product Parts
PartX
PartY
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Builder.RealWorld
{
// MainApp test application
Version: 1.0
Side: 27
Project: Design Pattern
shop.Construct(b2);
b2.Vehicle.Show();
shop.Construct(b3);
b3.Vehicle.Show();
// "Director"
class Shop
{
// Builder uses a complex series of steps
public void Construct(VehicleBuilder vehicleBuilder)
{
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWheels();
vehicleBuilder.BuildDoors();
}
}
// "Builder"
// Property
public Vehicle Vehicle
{
get{ return vehicle; }
}
// "ConcreteBuilder1"
Version: 1.0
Side: 28
Project: Design Pattern
{
vehicle = new Vehicle("MotorCycle");
vehicle["frame"] = "MotorCycle Frame";
}
// "ConcreteBuilder2"
// "ConcreteBuilder3"
Version: 1.0
Side: 29
Project: Design Pattern
// "Product"
class Vehicle
{
private string type;
private Hashtable parts = new Hashtable();
// Constructor
public Vehicle(string type)
{
this.type = type;
}
Output
---------------------------
Vehicle Type: Scooter
Frame : Scooter Frame
Engine : none
#Wheels: 2
#Doors : 0
Version: 1.0
Side: 30
Project: Design Pattern
---------------------------
Vehicle Type: Car
Frame : Car Frame
Engine : 2500 cc
#Wheels: 4
#Doors : 4
---------------------------
Vehicle Type: MotorCycle
Frame : MotorCycle Frame
Engine : 500 cc
#Wheels: 2
#Doors : 0
METHOD show.
DATA: parts_line TYPE ty_parts.
write: / '---------------------------------------------'.
WRITE: / 'Vehicle Type:' , vtype.
LOOP AT parts INTO parts_line.
WRITE: / parts_line-key, parts_line-part.
ENDLOOP.
Version: 1.0
Side: 31
Project: Design Pattern
ENDMETHOD. "show
ENDCLASS. "Vehicle IMPLEMENTATION
METHOD getvehicle.
vehicle = me->vehicle.
ENDMETHOD. "vehicle
METHOD show.
vehicle->show( ).
ENDMETHOD. "show
ENDCLASS. "vehiclebuilder IMPLEMENTATION
Version: 1.0
Side: 32
Project: Design Pattern
,builddoors REDEFINITION
.
ENDCLASS. "Carbuilder DEFINITION
Version: 1.0
Side: 33
Project: Design Pattern
vehiclebuilder->buildwheels( ).
vehiclebuilder->builddoors( ).
ENDMETHOD. "construct
ENDCLASS. "shop IMPLEMENTATION
ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Vehicle Type: Scooter
frame Scooter Frame
engine 50 cc
wheels 2
doors 0
2.1.3.1 Definition
Define an interface for creating an object, but let subclasses decide which class
to instantiate. Factory Method lets a class defer instantiation to subclasses.
Version: 1.0
Side: 34
Project: Design Pattern
2.1.3.3 Participants
The classes and/or objects participating in this pattern are:
o Product (Page)
o defines the interface of objects the factory method creates
o ConcreteProduct (SkillsPage, EducationPage, ExperiencePage)
o implements the Product interface
o Creator (Document)
o declares the factory method, which returns an object of type
Product. Creator may also define a default implementation of the
factory method that returns a default ConcreteProduct object. may
call the factory method to create a Product object.
o ConcreteCreator (Report, Resume)
o overrides the factory method to return an instance of a
ConcreteProduct.
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Factory.Structural
{
Version: 1.0
Side: 35
Project: Design Pattern
class MainApp
{
static void Main()
{
// An array of creators
Creator[] creators = new Creator[2];
creators[0] = new ConcreteCreatorA();
creators[1] = new ConcreteCreatorB();
// "Product"
// "ConcreteProductA"
// "ConcreteProductB"
// "Creator"
// "ConcreteCreator"
Version: 1.0
Side: 36
Project: Design Pattern
// "ConcreteCreator"
Output
Created ConcreteProductA
Created ConcreteProductB
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Factory.RealWorld
{
class MainApp
{
static void Main()
{
// Note: constructors call Factory Method
Document[] documents = new Document[2];
documents[0] = new Resume();
documents[1] = new Report();
Version: 1.0
Side: 37
Project: Design Pattern
// "Product"
// "ConcreteProduct"
// "ConcreteProduct"
// "ConcreteProduct"
// "ConcreteProduct"
// "ConcreteProduct"
// "ConcreteProduct"
// "ConcreteProduct"
// "ConcreteProduct"
// "Creator"
Version: 1.0
Side: 38
Project: Design Pattern
// Factory Method
public abstract void CreatePages();
}
// "ConcreteCreator"
// "ConcreteCreator"
Output
Resume -------
SkillsPage
EducationPage
ExperiencePage
Report -------
IntroductionPage
Version: 1.0
Side: 39
Project: Design Pattern
ResultsPage
ConclusionPage
SummaryPage
BibliographyPage
In ABAP Classes you can’t get the classname with build in functions.Often you
don’t need The classname, but sometimes when you process collection of
classes you need to do dependent class processes, and therefore you need to
know which class you are working with. Using a standard SAP class we are able
to get the class name. In the examples I have build this code into a macro for
easy use:
* Macro Definition
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
* Call macro with parameter <instans object> <returning name>
?get_class_name product class_name.
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
Version: 1.0
Side: 40
Project: Design Pattern
Version: 1.0
Side: 41
Project: Design Pattern
ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Output
ConcreteCreatorA Creates ProductA
Product =
CONCRETEPRODUCTA
ConcreteCreatorB Creates ProductB
Product =
CONCRETEPRODUCTB
In this example the Abstract class have been replaced by using interfaces.
Each subclass must implement the interface and each subclass can instantiate
their own class versiob decoupled from a common parent class as long it
implement the same interface.
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
INTERFACE product.
TYPES ty_productname(30) TYPE c.
DATA: name TYPE ty_productname.
METHODS:
get_name RETURNING value(name) TYPE ty_productname.
ENDINTERFACE.
Version: 1.0
Side: 42
Project: Design Pattern
PUBLIC SECTION.
INTERFACES:
product.
ENDCLASS. "concreteproductB DEFINITION
INTERFACE creator.
METHODS:
factorymethod RETURNING value(product) TYPE REF TO product.
ENDINTERFACE.
* Call macro to find out which Creator and Product are active
?get_class_name <fs> class_name.
Version: 1.0
Side: 43
Project: Design Pattern
CASE class_name.
WHEN 'CONCRETECREATORA'.
WRITE: / 'ConcreteCreatorA Creates Product A'.
WHEN 'CONCRETECREATORB'.
WRITE: / 'ConcreteCreatorB Creates Product B'.
ENDCASE.
product = <fs>->factorymethod( ) .
?get_class_name product class_name.
product_name = product->get_name( ).
WRITE: / 'Class= ', class_name,'Product =',product_name.
ENDLOOP.
ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Output
ConcreteCreatorA Creates ProductA
Class =
CONCRETEPRODUCTA
Product = ConcreteProductA
ConcreteCreatorB Creates ProductB
Class =
CONCRETEPRODUCTB
Product = ConcreteProductB
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
Version: 1.0
Side: 44
Project: Design Pattern
METHOD pages.
pages[] = oa_pages_coll[].
ENDMETHOD. "pages
METHOD createpages.
DATA: page TYPE REF TO page.
CREATE OBJECT page TYPE skillspage.
APPEND page TO oa_pages_coll.
ENDMETHOD. "createpages
ENDCLASS. "resume IMPLEMENTATION
Version: 1.0
Side: 45
Project: Design Pattern
METHOD createpages.
DATA: page TYPE REF TO page.
CREATE OBJECT page TYPE introductionpage.
APPEND page TO oa_pages_coll.
ENDMETHOD. "createpages
ENDCLASS. "report IMPLEMENTATION
Version: 1.0
Side: 46
Project: Design Pattern
ENDMETHOD. "main
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Output:
SKILLSPAGE
EDUCATIONPAGE
EXPERIENCEPAGE
Report contains following pages:
INTRODUCTIONPAGE
RESULTSPAGE
CONCLUSIONPAGE
SUMMARYPAGE
BIBLIOGRAPHYPAGE
2.1.4 Prototype
A fully initialized instance to be copied or cloned
2.1.4.1 Definition
Specify the kind of objects to create using a prototypical instance, and create
new objects by copying this prototype.
Version: 1.0
Side: 47
Project: Design Pattern
2.1.4.4 Participants
The classes and/or objects participating in this pattern are:
o Prototype (ColorPrototype)
o declares an interface for cloning itself
o ConcretePrototype (Color)
o implements an operation for cloning itself
o Client (ColorManager)
o creates a new object by asking a prototype to clone itself
using System;
namespace DoFactory.GangOfFour.Prototype.Structural
{
class MainApp
{
Version: 1.0
Side: 48
Project: Design Pattern
// "Prototype"
// Constructor
public Prototype(string id)
{
this.id = id;
}
// Property
public string Id
{
get{ return id; }
}
// "ConcretePrototype1"
// "ConcretePrototype2"
Version: 1.0
Side: 49
Project: Design Pattern
Output
Cloned: I
Cloned: II
*&---------------------------------------------------------------------*
*& Report ZPROTOTYPE_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zprototype_structural.
*----------------------------------------------------------------------*
* CLASS prototype DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS prototype DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING id TYPE string
,get_id RETURNING value(id) TYPE string
,clone ABSTRACT RETURNING value(prototype) TYPE REF TO prototype
.
PRIVATE SECTION.
DATA: id TYPE string.
ENDCLASS. "prototype DEFINITION
*----------------------------------------------------------------------*
* CLASS prototype IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS prototype IMPLEMENTATION.
METHOD constructor.
me->id = id.
ENDMETHOD. "constructor
METHOD get_id.
id = me->id.
Version: 1.0
Side: 50
Project: Design Pattern
ENDMETHOD. "get_id
ENDCLASS. "prototype IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS concreteprototype1 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype1 DEFINITION INHERITING FROM prototype.
PUBLIC SECTION.
METHODS:
clone REDEFINITION.
ENDCLASS. "concreteprototype1 DEFINITION
*----------------------------------------------------------------------*
* CLASS concreteprototype1 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype1 IMPLEMENTATION.
METHOD clone.
prototype = me.
ENDMETHOD. "clone
ENDCLASS. "concreteprototype1 IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS concreteprototype2 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype2 DEFINITION INHERITING FROM prototype.
PUBLIC SECTION.
METHODS:
clone REDEFINITION.
ENDCLASS. "concreteprototype2 DEFINITION
*----------------------------------------------------------------------*
* CLASS concreteprototype2 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteprototype2 IMPLEMENTATION.
METHOD clone.
prototype = me.
ENDMETHOD. "clone
ENDCLASS. "concreteprototype2 IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
Version: 1.0
Side: 51
Project: Design Pattern
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
data: p1 type REF TO concreteprototype1
,c1 type REF TO concreteprototype1
,p2 TYPe REF TO concreteprototype2
,c2 type REF TO concreteprototype2
,id type string
.
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Output
Program ZPROTOTYPE_STRUCTURAL
Cloned: {0} I
Cloned: {0} II
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Prototype.RealWorld
{
class MainApp
{
static void Main()
Version: 1.0
Side: 52
Project: Design Pattern
{
ColorManager colormanager = new ColorManager();
Color color;
name = "peace";
color = colormanager[name].Clone() as Color;
name = "flame";
color = colormanager[name].Clone() as Color;
// "Prototype"
// "ConcretePrototype"
// Constructor
public Color(int red, int green, int blue)
{
this.red = red;
this.green = green;
this.blue = blue;
}
Version: 1.0
Side: 53
Project: Design Pattern
Console.WriteLine(
"Cloning color RGB: {0,3},{1,3},{2,3}",
red, green, blue);
// Prototype manager
class ColorManager
{
Hashtable colors = new Hashtable();
// Indexer
public ColorPrototype this[string name]
{
get
{
return colors[name] as ColorPrototype;
}
set
{
colors.Add(name, value);
}
}
}
}
Output
Cloning color RGB: 255, 0, 0
Cloning color RGB: 128,211,128
Cloning color RGB: 211, 34, 20
In the clone method this example does not create a new instance, but merely
returns actual instans and thereby you have two variables pointing to the same
instance. A true clone would create a new instance copy all the instance
attributes from actual instanceto the new clone and thereby you would have a
real clone that can live it’s own life.
*&---------------------------------------------------------------------*
*& Report ZPROTOTYPE_REALWORLD
*&
*&---------------------------------------------------------------------*
*&
Version: 1.0
Side: 54
Project: Design Pattern
*&
*&---------------------------------------------------------------------*
REPORT zprototype_realworld.
*----------------------------------------------------------------------*
* CLASS colorprototype DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS colorprototype DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
clone ABSTRACT RETURNING value(colorprototype) TYPE REF TO colorprototype.
ENDCLASS. "prototype DEFINITION
*----------------------------------------------------------------------*
* CLASS color DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS color DEFINITION INHERITING FROM colorprototype.
PUBLIC SECTION.
METHODS:
constructor IMPORTING red TYPE i
green TYPE i
blue TYPE i
,clone REDEFINITION.
PROTECTED SECTION.
DATA: xred TYPE i
,xgreen TYPE i
,xblue TYPE i.
ENDCLASS. "concreteprototype1 DEFINITION
*----------------------------------------------------------------------*
* CLASS color IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS color IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
xred = red.
xgreen = green.
xblue = blue.
ENDMETHOD. "constructor
METHOD clone.
WRITE: / 'Cloning color RGB: {0,3},{1,3},{2,3}',
me->xred, me->xgreen, me->xblue.
colorprototype = me.
ENDMETHOD. "clone
ENDCLASS. "concreteprototype1 IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS colormanager DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS colormanager DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF ty_colors
,name TYPE string
,color TYPE REF TO colorprototype
,END OF ty_colors.
Version: 1.0
Side: 55
Project: Design Pattern
METHODS:
get IMPORTING name TYPE string RETURNING value(Pcolors) TYPE REF TO colorprototype
,set IMPORTING name TYPE string pcolor TYPE REF TO colorprototype.
.
ENDCLASS. "colormanager DEFINITION
*----------------------------------------------------------------------*
* CLASS colormanager IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS colormanager IMPLEMENTATION.
METHOD get.
DATA buffer TYPE ty_colors.
FIELD-SYMBOLS <fs> TYPE ty_colors.
READ TABLE me->colors WITH TABLE KEY name = name INTO buffer.
Pcolors = buffer-color.
ENDMETHOD. "get
method set.
DATA buffer TYPE ty_colors.
buffer-name = name.
buffer-color = pcolor.
INSERT buffer INTO TABLE colors.
endmethod.
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
data: colormanager type REF TO colormanager
,!color type REF TO color
,name type string
.
Version: 1.0
Side: 56
Project: Design Pattern
create OBJECT !color EXPORTING red = 128 green = 211 blue = 128 .
colormanager->set( EXPORTING name = 'peace' pcolor = !color ).
name = 'red'.
!color ?= colormanager->get( name ). "!color is a colorprototype
!color ?= !color->clone( ). "!color is a color
name = 'peace'.
!color ?= colormanager->get( name ). "!color is a colorprototype
!color ?= !color->clone( ). "!color is a color
name = 'flame'.
!color ?= colormanager->get( name ). "!color is a colorprototype
!color ?= !color->clone( ). "!color is a color
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Output:
Program ZPROTOTYPE_STRUCTURAL
2.1.5 Singleton
A class of which only a single instance can exist
2.1.5.1 Definition
Ensure a class has only one instance and provide a global point of access to it.
Version: 1.0
Side: 57
Project: Design Pattern
• Facade objects are often Singletons because only one Facade object is
required.
• State objects are often Singletons.
• Singletons are often preferred to global variables because:
o They don't pollute the global namespace (or, in languages with
namespaces, their containing namespace) with unnecessary
variables.
o They permit lazy allocation and initialization, where global variables
in many languages will always consume resources.
• Singletons behave differently depending on the lifetime of the virtual
machine. While a software development kit may start a new virtual
machine for every run which results in a new instance of the singleton
being created, calls to a singleton e.g. within the virtual machine of an
application server behave differently. There the virtual machine remains
alive, therefore the instance of the singleton remains as well. Running
the code again therefore can retrieve the "old" instance of the singleton
which then may be contaminated with values in local fields which are the
result of the first run.
• Main application in abap, if implemented as OOP style the
mainapplication class uses local singleton to assure that the program is
not run several times.
2.1.5.3 Implementation
The singleton pattern is implemented by creating a class with a method that
creates a new instance of the class if one does not exist.
Version: 1.0
Side: 58
Project: Design Pattern
The singleton are not useful for inheritage, as all inheritated classes only have
one common instance and because the superclass only have one attribute with
the created instance. Singleton classes should therefore be marked as FINAL.
Another reason for bad inheritance, is if the singleton superclass tries to create
instances, as the superclass does not know the local class, therefore we are
getting type casting problems. You can however use singleton in inheritage if
your own class has been registered in the dictionary {SE24} and if your class
has been registered as a friend to the singleton superclass. Your singleton
should then have an collection af classes of which only one instance per class
are allowed. But then you must use dynamic creation and thereby you need to
export the classname as a parameter to get_instance.
2.1.5.5 Participants
The classes and/or objects participating in this pattern are:
o Singleton (LoadBalancer)
o defines an Instance operation that lets clients access its unique
instance.
Instance is a class operation responsible for creating and maintaining its own
unique instance.
using System;
namespace DoFactory.GangOfFour.Singleton.Structural
{
class MainApp
{
Version: 1.0
Side: 59
Project: Design Pattern
{
// Constructor is protected -- cannot use new
Singleton s1 = Singleton.Instance();
Singleton s2 = Singleton.Instance();
if (s1 == s2)
{
Console.WriteLine("Objects are the same instance");
}
// "Singleton"
class Singleton
{
private static Singleton instance;
return instance;
}
}
}
Output
ÎObjects are the same instance
*&---------------------------------------------------------------------*
*& Report ZSINGLETON_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
Version: 1.0
Side: 60
Project: Design Pattern
*&---------------------------------------------------------------------*
REPORT zsingleton_structural.
*----------------------------------------------------------------------*
* CLASS singleton DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS singleton DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
METHODS:
constructor.
CLASS-METHODS:
instance RETURNING value(instance) TYPE REF TO singleton.
PRIVATE SECTION.
CLASS-DATA x_instance TYPE REF TO singleton.
ENDCLASS. "singleton DEFINITION
*----------------------------------------------------------------------*
* CLASS singleton IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS singleton IMPLEMENTATION.
METHOD constructor.
ENDMETHOD. "constructor
METHOD instance.
IF x_instance IS INITIAL.
CREATE OBJECT x_instance.
ENDIF.
instance = x_instance.
ENDMETHOD. "instance
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: s1 TYPE REF TO singleton
,s2 TYPE REF TO singleton
.
IF s1 = s2.
WRITE: / 'Objects are the same instance'.
ENDIF.
Version: 1.0
Side: 61
Project: Design Pattern
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
------------------------------------
Objects are the same instance
using System;
using System.Collections;
using System.Threading;
namespace DoFactory.GangOfFour.Singleton.RealWorld
{
class MainApp
{
static void Main()
{
LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
LoadBalancer b4 = LoadBalancer.GetLoadBalancer();
// Same instance?
if (b1 == b2 && b2 == b3 && b3 == b4)
{
Console.WriteLine("Same instance\n");
}
Version: 1.0
Side: 62
Project: Design Pattern
// "Singleton"
class LoadBalancer
{
private static LoadBalancer instance;
private ArrayList servers = new ArrayList();
// Constructor (protected)
protected LoadBalancer()
{
// List of available servers
servers.Add("ServerI");
servers.Add("ServerII");
servers.Add("ServerIII");
servers.Add("ServerIV");
servers.Add("ServerV");
}
return instance;
}
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
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
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 ).
METHOD server.
pserver = me->get( ).
ENDMETHOD. "server
*----------------------------------------------------------------------*
* 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
IF b1 = b2 AND b2 = b3 AND b3 = b4 .
WRITE: / 'Objects are the same instance'.
ENDIF.
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
I suggest you allways use local application class, since the singleton have
severe problems with inheritage. Give your application class the name
lcl_application. As singleton pattern describe, your class should be registered
Version: 1.0
Side: 66
Project: Design Pattern
as CREATE PRIVATE. The default static method should be name RUN() without
parameters.
2.2.1.1 Definition
Convert the interface of a class into another interface clients expect. Adapter
lets classes work together that couldn't otherwise because of incompatible
interfaces.
An adapter allows classes to work together that normally could not because of
incompatible interfaces by wrapping its own interface around that of an already
existing class.
The adapter is also responsible for handling any logic necessary to transform
data into a form that is useful for the consumer. For instance, if multiple
boolean values are stored as a single integer but your consumer requires a
'true'/'false', the adapter would be responsible for extracting the appropriate
values from the integer value.
• The Object Adapter pattern - In this type of adapter pattern, the adapter
contains an instance of the class it wraps. In this situation, the adapter
makes calls to the instance of the wrapped object.
Version: 1.0
Side: 67
Project: Design Pattern
ObjectAdapter ClassAdapter
The object adapter pattern expressed The class adapter pattern expressed in
in UML. The adapter hides the UML.
adaptee's interface from the client.
The ABAP language does not support multiple inheritage, but support
interfaces. With interfaces you are able to use the same interface in different
classes. You are also able to let one class use different and several interfaces
and thereby accomplish the same effect as in multiple inheritage.
A typical solution in SAP where you want to use adapters are when you in a
dialog application want to have an object tree shown in the left control. This
tree might have different objects to show. Therefore you create a number of
interfaces that all the objects involved should be able to respond to e.g. open
or show yourself. Every objects that can be part of the tree implement the
interface.
Version: 1.0
Side: 68
Project: Design Pattern
2.2.1.4 Participants
The classes and/or objects participating in this pattern are:
o Target (ChemicalCompound)
o defines the domain-specific interface that Client uses.
o Adapter (Compound)
o adapts the interface Adaptee to the Target interface.
o Adaptee (ChemicalDatabank)
o defines an existing interface that needs adapting.
o Client (AdapterApp)
o collaborates with objects conforming to the Target interface.
using System;
namespace DoFactory.GangOfFour.Adapter.Structural
{
class MainApp
{
static void Main()
{
// Create adapter and place a request
Target target = new Adapter();
target.Request();
Version: 1.0
Side: 69
Project: Design Pattern
// "Target"
class Target
{
public virtual void Request()
{
Console.WriteLine("Called Target Request()");
}
}
// "Adapter"
// "Adaptee"
class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Called SpecificRequest()");
}
}
}
Output
Called SpecificRequest()
*&---------------------------------------------------------------------*
*& Report ZDP_ADAPTER_STRUCTURAL
Version: 1.0
Side: 70
Project: Design Pattern
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_adapter_structural.
*----------------------------------------------------------------------*
* CLASS target DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS target DEFINITION.
PUBLIC SECTION.
METHODS:
request.
ENDCLASS. "target DEFINITION
*----------------------------------------------------------------------*
* CLASS target IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS target IMPLEMENTATION.
METHOD request.
WRITE: / 'Called Target Request()'.
ENDMETHOD. "request
ENDCLASS. "target IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS adaptee DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS adaptee DEFINITION.
PUBLIC SECTION.
METHODS:
specificrequest.
ENDCLASS. "adaptee DEFINITION
*----------------------------------------------------------------------*
* CLASS adaptee IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS adaptee IMPLEMENTATION.
METHOD specificrequest.
WRITE: / 'Called SpecificRequest()'.
ENDMETHOD. "specificrequest
ENDCLASS. "adaptee IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS adapter DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS adapter DEFINITION INHERITING FROM target.
PUBLIC SECTION.
METHODS:
constructor
,request REDEFINITION.
PRIVATE SECTION.
CLASS-DATA: adaptee TYPE REF TO adaptee.
ENDCLASS. "adapter DEFINITION
*----------------------------------------------------------------------*
Version: 1.0
Side: 71
Project: Design Pattern
METHOD request.
CALL METHOD adaptee->specificrequest( ).
ENDMETHOD. "request
ENDCLASS. "adapter IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
data: mytarget type REF TO target
,myadapter TYPE REF TO adapter
.
* create adapter and place request
create OBJECT myadapter.
* Upcasting
mytarget = myadapter.
call METHOD mytarget->request( ).
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT:
---------
Called SpecificRequest()
Version: 1.0
Side: 72
Project: Design Pattern
using System;
namespace DoFactory.GangOfFour.Adapter.RealWorld
{
class MainApp
{
static void Main()
{
// Non-adapted chemical compound
Compound stuff = new Compound("Unknown");
stuff.Display();
// "Target"
class Compound
{
protected string name;
protected float boilingPoint;
protected float meltingPoint;
protected double molecularWeight;
protected string molecularFormula;
// Constructor
public Compound(string name)
{
this.name = name;
}
// "Adapter"
Version: 1.0
Side: 73
Project: Design Pattern
// Constructor
public RichCompound(string name) : base(name)
{
}
base.Display();
Console.WriteLine(" Formula: {0}", molecularFormula);
Console.WriteLine(" Weight : {0}", molecularWeight);
Console.WriteLine(" Melting Pt: {0}", meltingPoint);
Console.WriteLine(" Boiling Pt: {0}", boilingPoint);
}
}
// "Adaptee"
class ChemicalDatabank
{
// The Databank 'legacy API'
public float GetCriticalPoint(string compound, string point)
{
float temperature = 0.0F;
// Melting Point
if (point == "M")
{
switch (compound.ToLower())
{
case "water" : temperature = 0.0F; break;
case "benzene" : temperature = 5.5F; break;
case "alcohol" : temperature = -114.1F; break;
}
}
// Boiling Point
else
{
switch (compound.ToLower())
{
case "water" : temperature = 100.0F; break;
case "benzene" : temperature = 80.1F; break;
case "alcohol" : temperature = 78.3F; break;
}
}
return temperature;
}
Version: 1.0
Side: 74
Project: Design Pattern
switch (compound.ToLower())
{
case "water" : structure = "H20"; break;
case "benzene" : structure = "C6H6"; break;
case "alcohol" : structure = "C2H6O2"; break;
}
return structure;
}
Output
Compound: Unknown ------
*&---------------------------------------------------------------------*
*& Report ZDP_ADAPTER_REALWORLD
*&
Version: 1.0
Side: 75
Project: Design Pattern
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_adapter_zdp_adapter_realworld.
TYPES:
_float TYPE float
,_double TYPE p LENGTH 4 DECIMALS 4
,_string TYPE string.
*----------------------------------------------------------------------*
* CLASS compound DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compound DEFINITION.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE _string
,display.
PROTECTED SECTION.
DATA: name TYPE _string
,boilingpoint TYPE _float
,meltingpoint TYPE _float
,molecularweight TYPE _double
,molecularformula TYPE _string
.
ENDCLASS. "compound DEFINITION
*----------------------------------------------------------------------*
* CLASS compound IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compound IMPLEMENTATION.
METHOD constructor.
me->name = name.
ENDMETHOD. "constructor
METHOD display.
WRITE: /, /2(30)'Compound: -----', name .
ENDMETHOD. "display
*----------------------------------------------------------------------*
* CLASS chemicaldatabank DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS chemicaldatabank DEFINITION.
PUBLIC SECTION.
METHODS:
getcriticalpoint
IMPORTING compound TYPE _string
point TYPE _string
RETURNING value(temperature) TYPE _float
,getmolecularstructure
IMPORTING compound TYPE _string
RETURNING value(structure) TYPE _string
,getmolecularweight
IMPORTING compound TYPE _string
RETURNING value(weight) TYPE _double
.
ENDCLASS. "adaptee DEFINITION
Version: 1.0
Side: 76
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS chemicaldatabank IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS chemicaldatabank IMPLEMENTATION.
METHOD getcriticalpoint.
CLEAR temperature .
CASE point.
WHEN 'M'.
CASE compound.
WHEN 'Water'.
temperature = '0.0'.
WHEN 'Benzene'.
temperature = '5.5'.
WHEN 'Alcohol'.
temperature = '-114.1'.
WHEN OTHERS.
ENDCASE.
WHEN OTHERS.
CASE compound.
WHEN 'Water'.
temperature = '100.0'.
WHEN 'Benzene'.
temperature = '80.1'.
WHEN 'Alcohol'.
temperature = '78.3'.
WHEN OTHERS.
temperature = temperature.
ENDCASE.
ENDCASE.
ENDMETHOD. "specificrequest
METHOD getmolecularstructure.
CLEAR structure .
CASE compound.
WHEN 'Water'.
structure = 'H2O'.
WHEN 'Benzene'.
structure = 'C6H6'.
WHEN 'Alcohol'.
structure = 'C2H6O2'.
WHEN OTHERS.
structure = structure.
ENDCASE.
ENDMETHOD. "getmolecularstructure
METHOD getmolecularweight.
CLEAR weight.
CASE compound.
WHEN 'Water'.
weight = '18.015'.
WHEN 'Benzene'.
weight = '78.1134'.
WHEN 'Alcohol'.
weight = '46.0688'.
WHEN OTHERS.
weight = weight.
ENDCASE.
ENDMETHOD. "getmolecularweight
*----------------------------------------------------------------------*
* CLASS Richcompound DEFINITION
*----------------------------------------------------------------------*
Version: 1.0
Side: 77
Project: Design Pattern
*
*----------------------------------------------------------------------*
CLASS richcompound DEFINITION INHERITING FROM compound.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,display REDEFINITION.
PRIVATE SECTION.
DATA:
bank TYPE REF TO chemicaldatabank.
*----------------------------------------------------------------------*
* CLASS Richcompound IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS richcompound IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor
EXPORTING
name = name.
CREATE OBJECT bank.
ENDMETHOD. "constructor
METHOD display.
boilingpoint = bank->getcriticalpoint( compound = me->name
point = 'B' ).
meltingpoint = bank->getcriticalpoint( compound = me->name
point = 'M' ).
molecularweight = bank->getmolecularweight( me->name ).
molecularformula = bank->getmolecularstructure( me->name ).
ENDMETHOD. "request
ENDCLASS. "Richcompound IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: mystuff TYPE REF TO compound
,mywater TYPE REF TO richcompound
,mybenzene TYPE REF TO richcompound
,myalcohol TYPE REF TO richcompound
.
Version: 1.0
Side: 78
Project: Design Pattern
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT:
--------
Compound: Unknown
Compound: Water
Formula: H2O
Weight: 18,0150
Melting Pt: 0,00
Boiling Pt: 100,00
Compound: Benzene
Formula: C6H6
Weight: 78,1134
Melting Pt: 5,50
Boiling Pt: 80,10
Compound: Alcohol
Formula: C2H6O2
Weight: 46,0688
Melting Pt: -114,10
Boiling Pt: 78,30
Version: 1.0
Side: 79
Project: Design Pattern
REPORT zdp_adapter_eksempel.
*----------------------------------------------------------------------*
* INTERFACE lif_figur
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_figur.
METHODS:
get_areal RETURNING value(areal) TYPE i.
ENDINTERFACE. "lif_figur
*----------------------------------------------------------------------*
* CLASS lcl_cirkel DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_cirkel DEFINITION.
PUBLIC SECTION.
DATA: radius TYPE i.
INTERFACES:
lif_figur.
ALIASES get_areal FOR lif_figur~get_areal.
METHODS:
constructor IMPORTING r TYPE i.
ENDCLASS. "lcl_cirkel DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_cirkel IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_cirkel IMPLEMENTATION.
METHOD constructor.
me->radius = r.
ENDMETHOD. "constructor
METHOD get_areal.
DATA: pi TYPE f.
pi = 22 / 7.
areal = ( me->radius ** 2 ) * pi.
ENDMETHOD. "get_areal
ENDCLASS. "lcl_cirkel IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_firkant DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_firkant DEFINITION.
PUBLIC SECTION.
DATA: laengde TYPE i
,bredde TYPE i.
INTERFACES:
lif_figur.
ALIASES get_areal FOR lif_figur~get_areal.
METHODS:
constructor IMPORTING l TYPE i b TYPE i.
ENDCLASS. "lcl_firkant DEFINITION
Version: 1.0
Side: 80
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS lcl_firkant IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_firkant IMPLEMENTATION.
METHOD constructor.
me->laengde = l.
me->bredde = b.
ENDMETHOD. "constructor
METHOD get_areal.
areal = me->laengde * me->bredde.
ENDMETHOD. "get_areal
ENDCLASS. "lcl_firkant IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_trekant DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_trekant DEFINITION.
PUBLIC SECTION.
DATA: hojde TYPE i
,grundlinie TYPE i.
INTERFACES:
lif_figur.
ALIASES get_areal FOR lif_figur~get_areal.
METHODS:
constructor IMPORTING h TYPE i g TYPE i.
ENDCLASS. "lcl_trekant DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_trekant IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_trekant IMPLEMENTATION.
METHOD constructor.
me->hojde = h.
me->grundlinie = g.
ENDMETHOD. "constructor
METHOD get_areal.
areal = ( me->hojde / 2 ) * me->grundlinie.
ENDMETHOD. "get_areal
ENDCLASS. "lcl_trekant IMPLEMENTATION
*----------------------------------------------------------
* CLASS lcl_application DEFINITION
* Pattern: SINGLETON
* Why: Definition create private ensures that nobody outside the
* class can create instances unless the class-method run()
* is activated and this method checks if an instance has
* allready been created.
*----------------------------------------------------------
CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.
Version: 1.0
Side: 81
Project: Design Pattern
*----------------------------------------------------------
* IMPLEMENTATION
*----------------------------------------------------------
CLASS lcl_application IMPLEMENTATION.
*----------------------------------------------------------
* LCL_APPLICATION->RUN().
*----------------------------------------------------------
METHOD run.
DATA:
exc_ref TYPE REF TO cx_root
,exc_text TYPE string .
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
*----------------------------------------------------------
* LCL_APPLICATION->CONSTRUCTOR().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA:
o_cirkel TYPE REF TO lcl_cirkel
,o_firkant TYPE REF TO lcl_firkant
,o_trekant TYPE REF TO lcl_trekant
,areal TYPE i
.
areal = o_trekant->get_areal( ).
WRITE:/ 'Trekantens areal er ', areal.
areal = o_firkant->get_areal( ).
WRITE:/ 'Firkantens areal er ', areal.
ENDMETHOD. "constructor
START-OF-SELECTION.
Version: 1.0
Side: 82
Project: Design Pattern
lcl_application=>run( ).
2.2.2 Bridge
Separates an object’s interface from its implementation
2.2.2.1 Definition
The bridge pattern is a design pattern used in software engineering which is
meant to "decouple an abstraction from its implementation so that the two can
vary independently" (Gamma et al.).
Car abstraction
Version: 1.0
Side: 83
Project: Design Pattern
Imagine two types of cars (the abstraction), a Jaguar and a Mercedes (both
are Refinements of the Abstraction). The Abstraction defines that a Car has
features such as tires and an engine. Refinements of the Abstraction declare
what specific kind of tires and engine it has.
Finally, there are two types of road. The road is the Implementor (see image
below). A highway and an interstate highway are the Implementation Details.
Any car refinement needs to be able to drive on any type of road; this concept
is what the Bridge Pattern is all about.
class diagram of the bridge design pattern, created by Nvineeth using dpatoolkit
2.2.2.4 Participants
2.2.2.5 Sample code In C#
2.2.3 Composite
A tree structure of simple and composite objects
2.2.3.1 Definition
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat
individual objects and compositions of objects uniformly.
The example could be more accurate, as the leaf can neither remove or add, and therefore these methods
should not be part of the component butmoved to the composite, the only common methods are the
constructor and display.
Version: 1.0
Side: 84
Project: Design Pattern
2.2.3.3 Participants
The classes and/or objects participating in this pattern are:
• Component (DrawingElement)
o declares the interface for objects in the composition. implements
default behavior for the interface common to all classes, as
appropriate. declares an interface for accessing and managing its
child components. (optional) defines an interface for accessing a
component's parent in the recursive structure, and implements it if
that's appropriate.
• Leaf (PrimitiveElement)
o represents leaf objects in the composition. A leaf has no children.
defines behavior for primitive objects in the composition.
• Composite (CompositeElement)
o defines behavior for components having children. stores child
components. implements child-related operations in the
Component interface.
• Client (CompositeApp)
o manipulates objects in the composition through the Component
interface.
Version: 1.0
Side: 85
Project: Design Pattern
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Composite.Structural
{
class MainApp
{
static void Main()
{
// Create a tree structure
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
root.Add(comp);
root.Add(new Leaf("Leaf C"));
// "Component"
// Constructor
public Component(string name)
{
this.name = name;
}
Version: 1.0
Side: 86
Project: Design Pattern
// "Composite"
// Constructor
public Composite(string name) : base(name)
{
}
// "Leaf"
Version: 1.0
Side: 87
Project: Design Pattern
}
}
Output
-root
---Leaf A
---Leaf B
---Composite X
-----Leaf XA
-----Leaf XB
---Leaf C
*&---------------------------------------------------------------------*
*& Report ZDP_COMPOSITE_STRUCTURAL
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_composite_structural.
*----------------------------------------------------------------------*
* CLASS component DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS component DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,add ABSTRACT IMPORTING component TYPE REF TO component
,remove ABSTRACT IMPORTING component TYPE REF TO component
,display ABSTRACT IMPORTING depth TYPE i
.
PROTECTED SECTION.
DATA: name TYPE string.
ENDCLASS. "component DEFINITION
*----------------------------------------------------------------------*
* CLASS component IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS component IMPLEMENTATION.
METHOD constructor.
me->name = name.
ENDMETHOD. "constructor
ENDCLASS. "component IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS composite DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS composite DEFINITION INHERITING FROM component.
PUBLIC SECTION.
Version: 1.0
Side: 88
Project: Design Pattern
METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(composite) TYPE REF TO composite .
PRIVATE SECTION.
DATA children TYPE TABLE OF REF TO component.
ENDCLASS. "composite DEFINITION
*----------------------------------------------------------------------*
* CLASS composite IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS composite IMPLEMENTATION.
METHOD add.
INSERT component INTO TABLE children.
ENDMETHOD. "add
METHOD remove.
FIELD-SYMBOLS <fs> TYPE REF TO component.
data: index type sy-tabix.
METHOD display.
FIELD-SYMBOLS <fs> TYPE REF TO component.
DATA mydepth TYPE i.
write: /.
do depth times.
write '-'.
enddo.
WRITE: me->name.
mydepth = depth + 1.
LOOP AT children ASSIGNING <fs>.
<fs>->display( EXPORTING depth = mydepth ).
ENDLOOP.
ENDMETHOD. "display
METHOD new.
CREATE OBJECT composite EXPORTING name = name.
ENDMETHOD. "new
*----------------------------------------------------------------------*
* CLASS leaf DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS leaf DEFINITION INHERITING FROM component.
PUBLIC SECTION.
Version: 1.0
Side: 89
Project: Design Pattern
METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(leaf) TYPE REF TO leaf .
ENDCLASS. "leaf DEFINITION
*----------------------------------------------------------------------*
* CLASS leaf IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS leaf IMPLEMENTATION.
METHOD add.
WRITE: / 'Cannot add to a leaf'.
ENDMETHOD. "add
METHOD remove.
WRITE: / 'Cannot remove from a leaf'.
ENDMETHOD. "remove
METHOD display.
write: /.
do depth times.
write '-'.
enddo.
WRITE: me->name.
ENDMETHOD. "display
METHOD new.
CREATE OBJECT leaf EXPORTING name = name.
ENDMETHOD. "new
ENDCLASS. "leaf IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: myroot TYPE REF TO composite
,myleaf TYPE REF TO leaf
,mycomposite TYPE REF TO composite
.
myroot = composite=>new('root').
myroot->add( mycomposite ).
myleaf = leaf=>new('Leaf C'). myroot->add( myleaf ).
Version: 1.0
Side: 90
Project: Design Pattern
myroot->display( 1 ).
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT:
- root
- - Leaf A
- - Leaf B
- - Composite X
- - - Leaf XA
- - - Leaf XB
- - Leaf C
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Composite.RealWorld
{
class MainApp
{
static void Main()
{
// Create a tree structure
CompositeElement root =
new CompositeElement("Picture");
root.Add(new PrimitiveElement("Red Line"));
root.Add(new PrimitiveElement("Blue Circle"));
root.Add(new PrimitiveElement("Green Box"));
CompositeElement comp =
new CompositeElement("Two Circles");
comp.Add(new PrimitiveElement("Black Circle"));
comp.Add(new PrimitiveElement("White Circle"));
root.Add(comp);
Version: 1.0
Side: 91
Project: Design Pattern
root.Display(1);
// "Component" Treenode
// Constructor
public DrawingElement(string name)
{
this.name = name;
}
// "Leaf"
// "Composite"
// Constructor
public CompositeElement(string name) : base(name)
{
}
Version: 1.0
Side: 92
Project: Design Pattern
Output
-+ Picture
--- Red Line
--- Blue Circle
--- Green Box
---+ Two Circles
----- Black Circle
----- White Circle
*&---------------------------------------------------------------------*
*& Report ZDP_COMPOSITE_REALWORLD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_composite_realworld.
*----------------------------------------------------------------------*
* CLASS DrawingElement DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS drawingelement DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,add ABSTRACT IMPORTING drawingelement TYPE REF TO drawingelement
,remove ABSTRACT IMPORTING drawingelement TYPE REF TO drawingelement
,display ABSTRACT IMPORTING indent TYPE i
.
PROTECTED SECTION.
Version: 1.0
Side: 93
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS DrawingElement IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS drawingelement IMPLEMENTATION.
METHOD constructor.
me->name = name.
ENDMETHOD. "constructor
ENDCLASS. "DrawingElement IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS compositeElement DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compositeelement DEFINITION INHERITING FROM drawingelement.
PUBLIC SECTION.
METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(compositeelement) TYPE REF TO compositeelement .
PRIVATE SECTION.
DATA elements TYPE TABLE OF REF TO drawingelement.
ENDCLASS. "compositeElement DEFINITION
*----------------------------------------------------------------------*
* CLASS compositeElement IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS compositeelement IMPLEMENTATION.
METHOD add.
INSERT drawingelement INTO TABLE elements.
ENDMETHOD. "add
METHOD remove.
FIELD-SYMBOLS <fs> TYPE REF TO drawingelement.
DATA: index TYPE sy-tabix.
METHOD display.
FIELD-SYMBOLS <fs> TYPE REF TO drawingelement.
DATA myindent TYPE i.
WRITE: /.
DO indent TIMES.
WRITE '-'.
ENDDO.
Version: 1.0
Side: 94
Project: Design Pattern
myindent = indent + 2.
LOOP AT elements ASSIGNING <fs>.
<fs>->display( EXPORTING indent = myindent ).
ENDLOOP.
ENDMETHOD. "display
METHOD new.
CREATE OBJECT compositeelement EXPORTING name = name.
ENDMETHOD. "new
*----------------------------------------------------------------------*
* CLASS PrimitiveElement DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS primitiveelement DEFINITION INHERITING FROM drawingelement.
PUBLIC SECTION.
METHODS:
add REDEFINITION
,remove REDEFINITION
,display REDEFINITION
.
CLASS-METHODS:
new IMPORTING name TYPE string
RETURNING value(primitiveelement) TYPE REF TO primitiveelement .
ENDCLASS. "PrimitiveElement DEFINITION
*----------------------------------------------------------------------*
* CLASS PrimitiveElement IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS primitiveelement IMPLEMENTATION.
METHOD add.
WRITE: / 'Cannot add to a PrimitiveElement'.
ENDMETHOD. "add
METHOD remove.
WRITE: / 'Cannot remove from a PrimitiveElement'.
ENDMETHOD. "remove
METHOD display.
WRITE: /.
DO indent TIMES.
WRITE '-'.
ENDDO.
WRITE: me->name.
ENDMETHOD. "display
METHOD new.
CREATE OBJECT primitiveelement EXPORTING name = name.
ENDMETHOD. "new
ENDCLASS. "PrimitiveElement IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
Version: 1.0
Side: 95
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: myroot TYPE REF TO compositeelement
,myprimitiveelement TYPE REF TO primitiveelement
,mycompositeelement TYPE REF TO compositeelement
.
myroot = compositeelement=>new('Picture').
myroot->display( 1 ).
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT:
- + Picture
- - - Red Line
- - - Blue Circle
- - - Gree Box
- - - + Two Circles
- - - - - Black Circle
- - - - - White Circle
2.2.4 Decorator
Add responsibilities to objects dynamically
2.2.4.1 Definition
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to
subclassing for extending functionality.
Version: 1.0
Side: 96
Project: Design Pattern
2.2.4.3 Participants
The classes and/or objects participating in this pattern are:
• Component (LibraryItem)
o defines the interface for objects that can have responsibilities added to them dynamically.
• ConcreteComponent (Book, Video)
o defines an object to which additional responsibilities can be attached.
• Decorator (Decorator)
o maintains a reference to a Component object and defines an interface that conforms to
Component's interface.
• ConcreteDecorator (Borrowable)
o adds responsibilities to the component.
using System;
namespace DoFactory.GangOfFour.Decorator.Structural
{
Version: 1.0
Side: 97
Project: Design Pattern
class MainApp
{
static void Main()
{
// Create ConcreteComponent and two Decorators
ConcreteComponent c = new ConcreteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
// Link decorators
d1.SetComponent(c);
d2.SetComponent(d1);
d2.Operation();
// "Component"
// "ConcreteComponent"
// "Decorator"
Version: 1.0
Side: 98
Project: Design Pattern
}
}
// "ConcreteDecoratorA"
// "ConcreteDecoratorB"
void AddedBehavior()
{
}
}
}
Output
ConcreteComponent.Operation()
ConcreteDecoratorA.Operation()
ConcreteDecoratorB.Operation()
REPORT zdp_decorator_structural.
*----------------------------------------------------------------------*
* CLASS component DEFINITION
*----------------------------------------------------------------------*
Version: 1.0
Side: 99
Project: Design Pattern
*
*----------------------------------------------------------------------*
CLASS component DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
operation ABSTRACT.
ENDCLASS. "component DEFINITION
*----------------------------------------------------------------------*
* CLASS concretecomponent DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecomponent DEFINITION INHERITING FROM component.
PUBLIC SECTION.
METHODS:
operation REDEFINITION.
ENDCLASS. "concretecomponent DEFINITION
*----------------------------------------------------------------------*
* CLASS concretecomponent IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecomponent IMPLEMENTATION.
METHOD operation.
WRITE: / 'ConcreteComponent.Operation()'.
ENDMETHOD. "operation
ENDCLASS. "concretecomponent IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS decorator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS decorator DEFINITION INHERITING FROM component ABSTRACT.
PUBLIC SECTION.
METHODS:
setcomponent IMPORTING component TYPE REF TO component
,operation REDEFINITION
.
PROTECTED SECTION.
DATA: component TYPE REF TO component.
ENDCLASS. "decorator DEFINITION
*----------------------------------------------------------------------*
* CLASS decorator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS decorator IMPLEMENTATION.
METHOD setcomponent.
me->component = component.
ENDMETHOD. "setcomponent
METHOD operation.
IF NOT component IS INITIAL.
component->operation( ).
ENDIF.
ENDMETHOD. "operation
ENDCLASS. "decorator IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS concretedecoratora DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratora DEFINITION INHERITING FROM decorator.
Version: 1.0
Side: 100
Project: Design Pattern
PUBLIC SECTION.
METHODS:
operation REDEFINITION.
PRIVATE SECTION.
DATA:
addedstate TYPE string.
ENDCLASS. "concretedecoratora DEFINITION
*----------------------------------------------------------------------*
* CLASS concretedecoratora IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratora IMPLEMENTATION.
METHOD operation.
super->operation( ).
addedstate = 'New State'.
WRITE: / 'ConcreteDecoratorA.Operation()'.
ENDMETHOD. "operation
ENDCLASS. "concretedecoratora IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS concretedecoratorb DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratorb DEFINITION INHERITING FROM decorator.
PUBLIC SECTION.
METHODS:
operation REDEFINITION
,addedbehavior
.
ENDCLASS. "concretedecoratorb DEFINITION
*----------------------------------------------------------------------*
* CLASS concretedecoratorb IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretedecoratorb IMPLEMENTATION.
METHOD operation.
super->operation( ).
me->addedbehavior( ).
WRITE: / 'ConcreteDecoratorB.Operation()'.
ENDMETHOD. "operation
METHOD addedbehavior.
ENDMETHOD. "addedbehavior
ENDCLASS. "concretedecoratorb IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: c TYPE REF TO concretecomponent
,d1 TYPE REF TO concretedecoratora
Version: 1.0
Side: 101
Project: Design Pattern
d1->setcomponent( c ).
d2->setcomponent( d1 ).
d2->operation( ).
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT:
---------------------
ConcreteComponent.Operation()
ConcreteDecoratorA.Operation()
ConcreteDecoratorB.Operation()
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Decorator.RealWorld
{
class MainApp
{
static void Main()
{
// Create book
Book book = new Book ("Worley", "Inside ASP.NET", 10);
book.Display();
// Create video
Video video = new Video ("Spielberg", "Jaws", 23, 92);
video.Display();
borrowvideo.Display();
Version: 1.0
Side: 102
Project: Design Pattern
// "Component"
// Property
public int NumCopies
{
get{ return numCopies; }
set{ numCopies = value; }
}
// "ConcreteComponent"
// Constructor
public Book(string author,string title,int numCopies)
{
this.author = author;
this.title = title;
this.NumCopies = numCopies;
}
// "ConcreteComponent"
// Constructor
public Video(string director, string title,
Version: 1.0
Side: 103
Project: Design Pattern
// "Decorator"
// Constructor
public Decorator(LibraryItem libraryItem)
{
this.libraryItem = libraryItem;
}
// "ConcreteDecorator"
// Constructor
public Borrowable(LibraryItem libraryItem)
: base(libraryItem)
{
}
Version: 1.0
Side: 104
Project: Design Pattern
borrowers.Remove(name);
libraryItem.NumCopies++;
}
Output
Book ------
Author: Worley
Title: Inside ASP.NET
# Copies: 10
Video -----
Director: Spielberg
Title: Jaws
# Copies: 23
Playtime: 92
Video -----
Director: Spielberg
Title: Jaws
# Copies: 21
Playtime: 92
borrower: Customer #1
borrower: Customer #2
*&---------------------------------------------------------------------*
*& Report ZDP_DECORATOR_REALWORLD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_decorator_realworld.
*----------------------------------------------------------------------*
* CLASS property DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
Version: 1.0
Side: 105
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS property IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS property IMPLEMENTATION.
METHOD get.
value = me->value.
ENDMETHOD. "get
METHOD set.
me->value = value.
ENDMETHOD. "set
ENDCLASS. "property IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS LibraryItem DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS libraryitem DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING numcopies TYPE i
,display ABSTRACT.
PROTECTED SECTION.
DATA: numcopies TYPE REF TO property.
ENDCLASS. "LibraryItem DEFINITION
*----------------------------------------------------------------------*
* CLASS libraryitem IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS libraryitem IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT me->numcopies.
me->numcopies->set( numcopies ).
ENDMETHOD. "constructor
ENDCLASS. "libraryitem IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS book DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS book DEFINITION INHERITING FROM libraryitem.
PUBLIC SECTION.
METHODS:
constructor IMPORTING author TYPE string
title TYPE string
numcopies TYPE i
,display REDEFINITION.
PRIVATE SECTION.
DATA:
author TYPE string
,title TYPE string
Version: 1.0
Side: 106
Project: Design Pattern
.
ENDCLASS. "book DEFINITION
*----------------------------------------------------------------------*
* CLASS book IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS book IMPLEMENTATION.
METHOD constructor.
super->constructor( numcopies ).
me->author = author.
me->title = title.
ENDMETHOD. "constructor
METHOD display.
DATA: numofcopies TYPE i.
WRITE: /, /2(20)'Book ---------------'.
WRITE: /5(15)'Author:........', author.
WRITE: /5(15)'Title:.........', title.
numofcopies = me->numcopies->get( ).
WRITE: /5(15)'# copies:......' , numofcopies .
ENDMETHOD. "display
*----------------------------------------------------------------------*
* CLASS video DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS video DEFINITION INHERITING FROM libraryitem.
PUBLIC SECTION.
METHODS:
constructor IMPORTING director TYPE string
title TYPE string
numcopies TYPE i
playtime TYPE i
,display REDEFINITION.
PRIVATE SECTION.
DATA:
director TYPE string
,title TYPE string
,playtime TYPE i
.
ENDCLASS. "video DEFINITION
*----------------------------------------------------------------------*
* CLASS video IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS video IMPLEMENTATION.
METHOD constructor.
super->constructor( numcopies ).
me->director = director.
me->title = title.
me->playtime = playtime.
ENDMETHOD. "constructor
METHOD display.
DATA: numofcopies TYPE i.
WRITE: /, /2(20)'Video --------------'.
WRITE: /5(15)'Director:......', director.
WRITE: /5(15)'Title:.........', title.
numofcopies = me->numcopies->get( ).
Version: 1.0
Side: 107
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS decorator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS decorator DEFINITION INHERITING FROM libraryitem ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING libraryitem TYPE REF TO libraryitem
,display REDEFINITION
.
PROTECTED SECTION.
DATA: libraryitem TYPE REF TO libraryitem.
METHOD constructor.
super->constructor( 1 ).
me->libraryitem = libraryitem.
ENDMETHOD. "constructor
METHOD display.
me->libraryitem->display( ).
ENDMETHOD. "display
*----------------------------------------------------------------------*
* CLASS borrowable DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS borrowable DEFINITION INHERITING FROM decorator.
PUBLIC SECTION.
METHODS:
borrowitem IMPORTING name TYPE string
,returnitem IMPORTING name TYPE string
,display REDEFINITION
.
PROTECTED SECTION.
DATA borrowers TYPE TABLE OF string.
*----------------------------------------------------------------------*
* CLASS borrowable IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS borrowable IMPLEMENTATION.
METHOD borrowitem.
DATA: numofcopies TYPE i.
INSERT name INTO TABLE borrowers.
Version: 1.0
Side: 108
Project: Design Pattern
numofcopies = me->libraryitem->numcopies->get( ).
SUBTRACT 1 FROM numofcopies.
me->libraryitem->numcopies->set( numofcopies ).
ENDMETHOD. "borrowitem
METHOD returnitem.
ENDMETHOD. "returnitem
METHOD display.
DATA name TYPE string.
super->display( ).
WRITE: /.
LOOP AT borrowers INTO name.
WRITE: /10(10)'Borrower:.', name.
ENDLOOP.
ENDMETHOD. "display
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: book TYPE REF TO book
,video TYPE REF TO video
,borrowvideo TYPE REF TO borrowable
.
CREATE OBJECT book EXPORTING author = 'Worley'
title = 'Inside ASP.NET'
numcopies = 10.
book->display( ).
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
Version: 1.0
Side: 109
Project: Design Pattern
OUTPUT:
-------
Book
Author:........ Worley
Title:......... Inside ASP.NET
# copies:...... 10
Video
Director:...... Spielberg
Title:......... Jaws
# copies:...... 23
Playtime:...... 92
Video
Director:...... Spielberg
Title:......... Jaws
# copies:...... 21
Playtime:...... 92
Borrower:. Customer #1
Borrower:. Customer #2
2.2.5 Facade
A single class that represents an entire subsystem
2.2.5.1 Definition
Provide a unified interface to a set of interfaces in a subsystem. Façade defines
a higher-level interface that makes the subsystem easier to use.
2.2.5.3 Participants
The classes and/or objects participating in this pattern are:
Version: 1.0
Side: 110
Project: Design Pattern
• Facade (MortgageApplication)
o knows which subsystem classes are responsible for a request.
delegates client requests to appropriate subsystem objects.
• Subsystem classes (Bank, Credit, Loan)
o implement subsystem functionality. handle work assigned by the
Facade object. have no knowledge of the facade and keep no
reference to it.
using System;
namespace DoFactory.GangOfFour.Facade.Structural
{
class MainApp
{
public static void Main()
{
Facade facade = new Facade();
facade.MethodA();
facade.MethodB();
// "Subsystem ClassA"
class SubSystemOne
{
public void MethodOne()
{
Console.WriteLine(" SubSystemOne Method");
}
}
// Subsystem ClassB"
class SubSystemTwo
{
public void MethodTwo()
{
Console.WriteLine(" SubSystemTwo Method");
}
Version: 1.0
Side: 111
Project: Design Pattern
// Subsystem ClassC"
class SubSystemThree
{
public void MethodThree()
{
Console.WriteLine(" SubSystemThree Method");
}
}
// Subsystem ClassD"
class SubSystemFour
{
public void MethodFour()
{
Console.WriteLine(" SubSystemFour Method");
}
}
// "Facade"
class Facade
{
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four;
public Facade()
{
one = new SubSystemOne();
two = new SubSystemTwo();
three = new SubSystemThree();
four = new SubSystemFour();
}
Version: 1.0
Side: 112
Project: Design Pattern
Output
MethodA() ----
SubSystemOne Method
SubSystemTwo Method
SubSystemFour Method
MethodB() ----
SubSystemTwo Method
SubSystemThree Method
REPORT zdp_facade_structural.
*----------------------------------------------------------------------*
* CLASS subsystemone DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemone DEFINITION.
PUBLIC SECTION.
METHODS:
methodone.
ENDCLASS. "subsystemone DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemone IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemone IMPLEMENTATION.
METHOD methodone.
WRITE: / 'SubsystemOne Method'.
ENDMETHOD. "methodone
ENDCLASS. "subsystemone IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS subsystemtwo DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemtwo DEFINITION.
PUBLIC SECTION.
METHODS:
methodtwo.
ENDCLASS. "subsystemtwo DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemtwo IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
Version: 1.0
Side: 113
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS subsystemThree DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemthree DEFINITION.
PUBLIC SECTION.
METHODS:
methodthree.
ENDCLASS. "subsystemThree DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemthree IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemthree IMPLEMENTATION.
METHOD methodthree.
WRITE: / 'SubsystemThree Method'.
ENDMETHOD. "methodthree
ENDCLASS. "subsystemthree IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS subsystemfour DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemfour DEFINITION.
PUBLIC SECTION.
METHODS:
methodfour.
ENDCLASS. "subsystemfour DEFINITION
*----------------------------------------------------------------------*
* CLASS subsystemfour IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subsystemfour IMPLEMENTATION.
METHOD methodfour.
WRITE: / 'SubsystemFour Method'.
ENDMETHOD. "methodfour
ENDCLASS. "subsystemfour IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS facade DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS facade DEFINITION.
PUBLIC SECTION.
DATA:
one TYPE REF TO subsystemone
,two TYPE REF TO subsystemtwo
,three TYPE REF TO subsystemthree
,four TYPE REF TO subsystemfour
.
METHODS:
constructor
,methoda
Version: 1.0
Side: 114
Project: Design Pattern
,methodb
.
ENDCLASS. "facade DEFINITION
*----------------------------------------------------------------------*
* CLASS facade IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS facade IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT one.
CREATE OBJECT two.
CREATE OBJECT three.
CREATE OBJECT four.
ENDMETHOD. "constructor
METHOD methoda.
WRITE: /, / 'MethodA() ----'.
one->methodone( ).
two->methodtwo( ).
four->methodfour( ).
ENDMETHOD. "methoda
METHOD methodb.
WRITE: /, / 'MethodB() ----'.
two->methodtwo( ).
three->methodthree( ).
ENDMETHOD. "methodb
ENDCLASS. "facade IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: facade TYPE REF TO facade.
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT:
---------
MethodA()
SubsystemOne Method
SubsystemTwo Method
SubsystemFour Method
Version: 1.0
Side: 115
Project: Design Pattern
MethodB()
SubsystemTwo Method
SubsystemThree Method
using System;
namespace DoFactory.GangOfFour.Facade.RealWorld
{
// MainApp test application
class MainApp
{
static void Main()
{
// Facade
Mortgage mortgage = new Mortgage();
Console.WriteLine("\n" + customer.Name +
" has been " + (eligable ? "Approved" : "Rejected"));
// "Subsystem ClassA"
class Bank
{
public bool HasSufficientSavings(Customer c, int amount)
{
Console.WriteLine("Check bank for " + c.Name);
return true;
}
}
// "Subsystem ClassB"
class Credit
{
public bool HasGoodCredit(Customer c)
Version: 1.0
Side: 116
Project: Design Pattern
{
Console.WriteLine("Check credit for " + c.Name);
return true;
}
}
// "Subsystem ClassC"
class Loan
{
public bool HasNoBadLoans(Customer c)
{
Console.WriteLine("Check loans for " + c.Name);
return true;
}
}
class Customer
{
private string name;
// Constructor
public Customer(string name)
{
this.name = name;
}
// Property
public string Name
{
get{ return name; }
}
}
// "Facade"
class Mortgage
{
private Bank bank = new Bank();
private Loan loan = new Loan();
private Credit credit = new Credit();
Version: 1.0
Side: 117
Project: Design Pattern
eligible = false;
}
else if (!credit.HasGoodCredit(cust))
{
eligible = false;
}
return eligible;
}
}
}
Output
Ann McKinsey applies for $125,000.00 loan
REPORT zdp_facade_realworld.
*----------------------------------------------------------------------*
* CLASS customer DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS customer DEFINITION.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,getname RETURNING value(name) TYPE string
.
PRIVATE SECTION.
DATA: name TYPE string.
Version: 1.0
Side: 118
Project: Design Pattern
METHOD getname.
name = me->name.
ENDMETHOD. "getname
ENDCLASS. "customer IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS bank DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS bank DEFINITION.
PUBLIC SECTION.
METHODS:
hassufficientsavings
IMPORTING
customer TYPE REF TO customer
amount TYPE i
RETURNING value(val) TYPE boolean
.
ENDCLASS. "bank DEFINITION
*----------------------------------------------------------------------*
* CLASS bank IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS bank IMPLEMENTATION.
METHOD hassufficientsavings.
DATA: myname TYPE string.
myname = customer->getname( ).
WRITE: / 'Check bank for ', myname.
val = 'X'. "~TRUE
ENDMETHOD. "hassufficientsavings
ENDCLASS. "bank IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS credit DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS credit DEFINITION.
PUBLIC SECTION.
METHODS:
hasgoodcredit
IMPORTING
customer TYPE REF TO customer
RETURNING value(value) TYPE boolean
.
Version: 1.0
Side: 119
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS loan DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS loan DEFINITION.
PUBLIC SECTION.
METHODS:
hasnobadloans
IMPORTING
customer TYPE REF TO customer
RETURNING value(value) TYPE boolean.
ENDCLASS. "loan DEFINITION
*----------------------------------------------------------------------*
* CLASS loan IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS loan IMPLEMENTATION.
METHOD hasnobadloans.
DATA: mycustomer TYPE string.
mycustomer = customer->getname( ).
WRITE: / 'Check loans for ', mycustomer.
value = 'X'. "~true
ENDMETHOD. "hasnobadloans
ENDCLASS. "loan IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mortgage DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mortgage DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
,iseligible
IMPORTING
customer TYPE REF TO customer
amount TYPE i
RETURNING value(value) TYPE boolean
.
PRIVATE SECTION.
DATA: bank TYPE REF TO bank
,loan TYPE REF TO loan
,credit TYPE REF TO credit
.
ENDCLASS. "mortgage DEFINITION
*----------------------------------------------------------------------*
* CLASS mortgage IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mortgage IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT bank.
CREATE OBJECT loan.
CREATE OBJECT credit.
ENDMETHOD. "constructor
METHOD iseligible.
DATA: customername TYPE string.
customername = customer->getname( ).
Version: 1.0
Side: 120
Project: Design Pattern
ENDMETHOD. "iseligible
ENDCLASS. "mortgage IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
DATA: mortgage TYPE REF TO mortgage
,customer TYPE REF TO customer
,eligible TYPE boolean
,customername TYPE string
.
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT
-------------
Ann McKinsey applies for 125.000 loan
Check bank for Ann McKinsey
Check loans for Ann McKinsey
Check credit for Ann McKinsey
Version: 1.0
Side: 121
Project: Design Pattern
2.2.6.1 Definition
Use sharing to support large numbers of fine-grained (fin kornet) objects
efficiently.
2.2.6.3 Participants
The classes and/or objects participating in this pattern are:
• Flyweight (Character)
o declares an interface through which flyweights can receive and act
on extrinsic state. (udefra kommende/ydre)
• ConcreteFlyweight (CharacterA, CharacterB, ..., CharacterZ)
o implements the Flyweight interface and adds storage for intrinsic
state, if any. A ConcreteFlyweight object must be sharable. Any
state it stores must be intrinsic, (indre/indefra kommende) that is,
it must be independent of the ConcreteFlyweight object's context.
• UnsharedConcreteFlyweight ( not used )
o not all Flyweight subclasses need to be shared. The Flyweight
interface enables sharing, but it doesn't enforce it. It is common
for UnsharedConcreteFlyweight objects to have ConcreteFlyweight
objects as children at some level in the flyweight object structure
(as the Row and Column classes have).
• FlyweightFactory (CharacterFactory)
o creates and manages flyweight objects ensures that flyweight are
shared properly. When a client requests a flyweight, the
FlyweightFactory objects supplies an existing instance or creates
one, if none exists.
Version: 1.0
Side: 122
Project: Design Pattern
• Client (FlyweightApp)
o maintains a reference to flyweight(s). computes or stores the
extrinsic state of flyweight(s).
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Flyweight.Structural
{
// MainApp test application
class MainApp
{
static void Main()
{
// Arbitrary extrinsic state
int extrinsicstate = 22;
Flyweight fy = f.GetFlyweight("Y");
fy.Operation(--extrinsicstate);
Flyweight fz = f.GetFlyweight("Z");
fz.Operation(--extrinsicstate);
UnsharedConcreteFlyweight uf = new
UnsharedConcreteFlyweight();
uf.Operation(--extrinsicstate);
// "FlyweightFactory"
class FlyweightFactory
{
private Hashtable flyweights = new Hashtable();
// Constructor
Version: 1.0
Side: 123
Project: Design Pattern
public FlyweightFactory()
{
flyweights.Add("X", new ConcreteFlyweight());
flyweights.Add("Y", new ConcreteFlyweight());
flyweights.Add("Z", new ConcreteFlyweight());
}
// "Flyweight"
// "ConcreteFlyweight"
// "UnsharedConcreteFlyweight"
Output
ConcreteFlyweight: 21
ConcreteFlyweight: 20
ConcreteFlyweight: 19
UnsharedConcreteFlyweight: 18
Version: 1.0
Side: 124
Project: Design Pattern
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_flyweight_structural.
*----------------------------------------------------------------------*
* CLASS flyweight DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS flyweight DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
operation ABSTRACT IMPORTING extrincicstate TYPE i.
ENDCLASS. "flyweight DEFINITION
*----------------------------------------------------------------------*
* CLASS concreteflyweight DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteflyweight DEFINITION INHERITING FROM flyweight.
PUBLIC SECTION.
METHODS:
operation REDEFINITION.
ENDCLASS. "concreteflyweight DEFINITION
*----------------------------------------------------------------------*
* CLASS concreteflyweight IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concreteflyweight IMPLEMENTATION.
METHOD operation.
WRITE: /5(20)'ConcreteFlyweight', extrincicstate.
ENDMETHOD. "operation
ENDCLASS. "concreteflyweight IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS unsharedconcreteflyweight DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS unsharedconcreteflyweight DEFINITION INHERITING FROM flyweight.
PUBLIC SECTION.
METHODS:
operation REDEFINITION.
ENDCLASS. "unsharedconcreteflyweight DEFINITION
*----------------------------------------------------------------------*
* CLASS unsharedconcreteflyweight IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS unsharedconcreteflyweight IMPLEMENTATION.
METHOD operation.
WRITE: /5(20)'UnsharedConcreteFlyweight', extrincicstate.
ENDMETHOD. "operation
ENDCLASS. "unsharedconcreteflyweight IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS flyweightfactory DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
Version: 1.0
Side: 125
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS flyweightfactory IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS flyweightfactory IMPLEMENTATION.
METHOD constructor.
DATA: cf TYPE REF TO concreteflyweight
,buffer TYPE ty_flyweight .
*----------------------------------------------------------------------*
* CLASS mainapp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS. "mainapp DEFINITION
*----------------------------------------------------------------------*
* CLASS mainapp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mainapp IMPLEMENTATION.
METHOD main.
Version: 1.0
Side: 126
Project: Design Pattern
extrincicstate = 22.
CREATE OBJECT f.
fx = f->getflyweight( 'X' ).
subtract 1 from extrincicstate.
fx->operation( extrincicstate ).
ENDMETHOD. "endmethod
ENDCLASS. "mainapp IMPLEMENTATION
START-OF-SELECTION.
mainapp=>main( ).
OUTPUT:
-----------------
ConcreteFlyweight 21
ConcreteFlyweight 20
ConcreteFlyweight 19
UnsharedConcreteFlyw 18
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.
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Flyweight.RealWorld
{
Version: 1.0
Side: 127
Project: Design Pattern
class MainApp
{
static void Main()
{
// Build a document with text
string document = "AAZZBBZB";
char[] chars = document.ToCharArray();
// extrinsic state
int pointSize = 10;
// "FlyweightFactory"
class CharacterFactory
{
private Hashtable characters = new Hashtable();
// "Flyweight"
Version: 1.0
Side: 128
Project: Design Pattern
// "ConcreteFlyweight"
// "ConcreteFlyweight"
// ... C, D, E, etc.
Version: 1.0
Side: 129
Project: Design Pattern
// "ConcreteFlyweight"
Output
A (pointsize 11)
A (pointsize 12)
Z (pointsize 13)
Z (pointsize 14)
B (pointsize 15)
B (pointsize 16)
Z (pointsize 17)
B (pointsize 18)
2.2.7 Proxy
An object representing another object
2.2.7.1 Definition
Provide a surrogate or placeholder for another object to control access to it.
Version: 1.0
Side: 130
Project: Design Pattern
2.2.7.3 Participants
The classes and/or objects participating in this pattern are:
• Proxy (MathProxy)
o maintains a reference that lets the proxy access the real subject.
Proxy may refer to a Subject if the RealSubject and Subject
interfaces are the same. provides an interface identical to Subject's
so that a proxy can be substituted for for the real subject. controls
access to the real subject and may be responsible for creating and
deleting it. other responsibilites depend on the kind of proxy:
remote proxies are responsible for encoding a request and its
arguments and for sending the encoded request to the real
subject in a different address space.
virtual proxies may cache additional information about the
real subject so that they can postpone accessing it. For
example, the ImageProxy from the Motivation caches the
real images's extent.
protection proxies check that the caller has the access
permissions required to perform a request.
• Subject (IMath)
o defines the common interface for RealSubject and Proxy so that a
Proxy can be used anywhere a RealSubject is expected.
• RealSubject (Math)
o defines the real object that the proxy represents.
Version: 1.0
Side: 131
Project: Design Pattern
using System;
namespace DoFactory.GangOfFour.Proxy.Structural
{
class MainApp
{
static void Main()
{
// Create proxy and request a service
Proxy proxy = new Proxy();
proxy.Request();
// "Subject"
// "RealSubject"
// "Proxy"
realSubject.Request();
}
}
}
Version: 1.0
Side: 132
Project: Design Pattern
Output
Called RealSubject.Request()
REPORT zdp_proxy_structural.
*----------------------------------------------------------------------*
* CLASS subject DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS subject DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
request ABSTRACT.
ENDCLASS. "subject DEFINITION
*----------------------------------------------------------------------*
* CLASS realsubject DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS realsubject DEFINITION INHERITING FROM subject.
PUBLIC SECTION.
METHODS:
request REDEFINITION.
ENDCLASS. "realsubject DEFINITION
*----------------------------------------------------------------------*
* CLASS realsubject IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS realsubject IMPLEMENTATION.
METHOD request.
WRITE: / 'Called RealSubject.Request()'.
ENDMETHOD. "request
ENDCLASS. "realsubject IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS proxy DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS proxy DEFINITION INHERITING FROM subject.
PUBLIC SECTION.
DATA: realsubject TYPE REF TO realsubject.
METHODS:
Version: 1.0
Side: 133
Project: Design Pattern
request REDEFINITION.
ENDCLASS. "proxy DEFINITION
*----------------------------------------------------------------------*
* CLASS proxy IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS proxy IMPLEMENTATION.
METHOD request.
* use lazy initialization
IF me->realsubject IS INITIAL.
CREATE OBJECT realsubject.
ENDIF.
me->realsubject->request( ).
ENDMETHOD. "request
ENDCLASS. "proxy IMPLEMENTATION
*----------------------------------------------------------
* CLASS lcl_application DEFINITION
*----------------------------------------------------------
CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.
ENDCLASS. "lcl_application DEFINITION
*----------------------------------------------------------
* IMPLEMENTATION
*----------------------------------------------------------
CLASS lcl_application IMPLEMENTATION.
*----------------------------------------------------------
* LCL_APPLICATION->RUN().
*----------------------------------------------------------
METHOD run.
DATA:
exc_ref TYPE REF TO cx_root
,exc_text TYPE string.
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
*----------------------------------------------------------
* LCL_APPLICATION->CONSTRUCTOR().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA: proxy TYPE REF TO proxy.
CREATE OBJECT proxy.
Version: 1.0
Side: 134
Project: Design Pattern
proxy->request( ).
ENDMETHOD. "constructor
START-OF-SELECTION.
lcl_application=>run( ).
Output:
Program ZDP_PROXY_STRUCTURAL
Called RealSubject.Request()
using System;
namespace DoFactory.GangOfFour.Proxy.RealWorld
{
class MainApp
{
static void Main()
{
// Create math proxy
MathProxy p = new MathProxy();
// Do the math
Console.WriteLine("4 + 2 = " + p.Add(4, 2));
Console.WriteLine("4 - 2 = " + p.Sub(4, 2));
Console.WriteLine("4 * 2 = " + p.Mul(4, 2));
Console.WriteLine("4 / 2 = " + p.Div(4, 2));
// "Subject"
Version: 1.0
Side: 135
Project: Design Pattern
// "RealSubject"
// "Proxy Object"
public MathProxy()
{
math = new Math();
}
Output
4 + 2 = 6
4 - 2 = 2
4 * 2 = 8
4 / 2 = 2
Version: 1.0
Side: 136
Project: Design Pattern
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_proxy_realworld.
*----------------------------------------------------------------------*
* INTERFACE if_math
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE if_math.
METHODS:
add IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
,sub IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
,mul IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
,div IMPORTING x TYPE i y TYPE i RETURNING value(v) TYPE i
.
ENDINTERFACE. "if_math
*----------------------------------------------------------------------*
* CLASS math DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS math DEFINITION.
PUBLIC SECTION.
INTERFACES:
if_math.
ALIASES:
add FOR if_math~add
,sub FOR if_math~sub
,mul FOR if_math~mul
,div FOR if_math~div.
ENDCLASS. "math DEFINITION
*----------------------------------------------------------------------*
* CLASS math IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS math IMPLEMENTATION.
METHOD add.
v = x + y.
ENDMETHOD. "add
METHOD sub.
v = x - y.
ENDMETHOD. "sub
METHOD mul.
v = x * y.
ENDMETHOD. "mul
METHOD div.
v = x DIV y.
ENDMETHOD. "div
ENDCLASS. "math IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS mathproxy DEFINITION
Version: 1.0
Side: 137
Project: Design Pattern
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mathproxy DEFINITION.
PUBLIC SECTION.
DATA: math TYPE REF TO math.
INTERFACES:
if_math.
ALIASES:
add FOR if_math~add
,sub FOR if_math~sub
,mul FOR if_math~mul
,div FOR if_math~div.
METHODS:
constructor.
ENDCLASS. "mathproxy DEFINITION
*----------------------------------------------------------------------*
* CLASS mathproxy IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS mathproxy IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT math.
ENDMETHOD. "constructor
METHOD add.
v = math->add( x = x y = y ).
ENDMETHOD. "add
METHOD sub.
v = math->sub( x = x y = y ).
ENDMETHOD. "sub
METHOD mul.
v = math->mul( x = x y = y ).
ENDMETHOD. "mul
METHOD div.
v = math->div( x = x y = y ).
ENDMETHOD. "div
ENDCLASS. "mathproxy IMPLEMENTATION
*----------------------------------------------------------------------*
*----------------------------------------------------------
* CLASS lcl_application DEFINITION
*----------------------------------------------------------
CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.
ENDCLASS. "lcl_application DEFINITION
*----------------------------------------------------------
* IMPLEMENTATION
*----------------------------------------------------------
CLASS lcl_application IMPLEMENTATION.
*----------------------------------------------------------
* LCL_APPLICATION->RUN().
Version: 1.0
Side: 138
Project: Design Pattern
*----------------------------------------------------------
METHOD run.
DATA:
exc_ref TYPE REF TO cx_root
,exc_text TYPE string.
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
*----------------------------------------------------------
* LCL_APPLICATION->CONSTRUCTOR().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA: p TYPE REF TO mathproxy
,result TYPE i
.
CREATE OBJECT p.
* do the math
result = p->add( x = 4 y = 2 ).
WRITE:/ '4 + 2 = ', result.
result = p->sub( x = 4 y = 2 ).
WRITE:/ '4 - 2 = ', result.
result = p->mul( x = 4 y = 2 ).
WRITE:/ '4 * 2 = ', result.
result = p->div( x = 4 y = 2 ).
WRITE:/ '4 / 2 = ', result.
ENDMETHOD. "constructor
START-OF-SELECTION.
lcl_application=>run( ).
2.3.1.1 Definition
Avoid coupling the sender of a request to its receiver by giving more than one
object a chance to handle the request. Chain the receiving objects and pass
Version: 1.0
Side: 139
Project: Design Pattern
the request along the chain until an object handles it. The client do know which
of the receiver that are the first I the chain.
2.3.1.3 Participants
The classes and/or objects participating in this pattern are:
• Handler (Approver)
o defines an interface for handling the requests (optional)
implements the successor link
• ConcreteHandler (Director, VicePresident, President)
o handles requests it is responsible for can access its successor if the
ConcreteHandler can handle the request, it does so; otherwise it
forwards the request to its successor
• Client (ChainApp)
o initiates the request to a ConcreteHandler object on the chain
using System;
namespace DoFactory.GangOfFour.Chain.Structural
{
// MainApp test application
class MainApp
{
static void Main()
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
Version: 1.0
Side: 140
Project: Design Pattern
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
// "Handler"
// "ConcreteHandler2"
Version: 1.0
Side: 141
Project: Design Pattern
// "ConcreteHandler3"
Output
ConcreteHandler1 handled request 2
ConcreteHandler1 handled request 5
ConcreteHandler2 handled request 14
ConcreteHandler3 handled request 22
ConcreteHandler2 handled request 18
ConcreteHandler1 handled request 3
ConcreteHandler3 handled request 27
ConcreteHandler3 handled request 20
REPORT zdp_chainofresp_structural.
CLASS cl_abap_typedescr DEFINITION LOAD.
Version: 1.0
Side: 142
Project: Design Pattern
*----------------------------------------------------------------------*
* Global Data
*----------------------------------------------------------------------*
DATA: moff TYPE i
,slen TYPE i
,mlen TYPE i.
*----------------------------------------------------------------------*
* Macro ?get_class_name returns the class name of the class
* Importing &1 Any Class
* Exporting &2 The name of the Class &1
*----------------------------------------------------------------------*
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
*----------------------------------------------------------------------*
* CLASS handler DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS handler DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
setsuccessor IMPORTING successor TYPE REF TO handler
,handlerequest ABSTRACT IMPORTING request TYPE i
.
PROTECTED SECTION.
DATA:
successor TYPE REF TO handler.
*----------------------------------------------------------------------*
* CLASS concretehandler1 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler1 DEFINITION INHERITING FROM handler.
PUBLIC SECTION.
METHODS:
handlerequest REDEFINITION.
ENDCLASS. "concretehandler1 DEFINITION
*----------------------------------------------------------------------*
* CLASS concretehandler1 IMPLEMENTATION
Version: 1.0
Side: 143
Project: Design Pattern
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler1 IMPLEMENTATION.
METHOD handlerequest.
DATA: class_name TYPE abap_abstypename.
?get_class_name me class_name.
*----------------------------------------------------------------------*
* CLASS concretehandler2 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler2 DEFINITION INHERITING FROM handler.
PUBLIC SECTION.
METHODS:
handlerequest REDEFINITION.
ENDCLASS. "concretehandler2 DEFINITION
*----------------------------------------------------------------------*
* CLASS concretehandler2 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler2 IMPLEMENTATION.
METHOD handlerequest.
DATA: class_name TYPE abap_abstypename.
?get_class_name me class_name.
*----------------------------------------------------------------------*
* CLASS concretehandler3 DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretehandler3 DEFINITION INHERITING FROM handler.
PUBLIC SECTION.
METHODS:
handlerequest REDEFINITION.
ENDCLASS. "concretehandler3 DEFINITION
*----------------------------------------------------------------------*
* CLASS concretehandler3 IMPLEMENTATION
*----------------------------------------------------------------------*
*
Version: 1.0
Side: 144
Project: Design Pattern
*----------------------------------------------------------------------*
CLASS concretehandler3 IMPLEMENTATION.
METHOD handlerequest.
DATA: class_name TYPE abap_abstypename.
?get_class_name me class_name.
*----------------------------------------------------------
* CLASS lcl_application DEFINITION
*----------------------------------------------------------
CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.
ENDCLASS. "lcl_application DEFINITION
*----------------------------------------------------------
* IMPLEMENTATION
*----------------------------------------------------------
CLASS lcl_application IMPLEMENTATION.
*----------------------------------------------------------
* LCL_APPLICATION->RUN().
*----------------------------------------------------------
METHOD run.
DATA:
exc_ref TYPE REF TO cx_root
,exc_text TYPE string.
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
*----------------------------------------------------------
* LCL_APPLICATION->CONSTRUCTOR().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA:
h1 TYPE REF TO concretehandler1
,h2 TYPE REF TO concretehandler2
,h3 TYPE REF TO concretehandler3
Version: 1.0
Side: 145
Project: Design Pattern
* create objects
CREATE OBJECT h1.
CREATE OBJECT h2.
CREATE OBJECT h3.
h1->setsuccessor( h2 ).
h2->setsuccessor( h3 ).
ENDMETHOD. "constructor
START-OF-SELECTION.
lcl_application=>run( ).
using System;
namespace DoFactory.GangOfFour.Chain.RealWorld
{
class MainApp
{
static void Main()
{
// Setup Chain of Responsibility
Director Larry = new Director();
VicePresident Sam = new VicePresident();
President Tammy = new President();
Larry.SetSuccessor(Sam);
Version: 1.0
Side: 146
Project: Design Pattern
Sam.SetSuccessor(Tammy);
// "Handler"
// "ConcreteHandler"
// "ConcreteHandler"
Version: 1.0
Side: 147
Project: Design Pattern
{
Console.WriteLine("{0} approved request# {1}",
this.GetType().Name, purchase.Number);
}
else if (successor != null)
{
successor.ProcessRequest(purchase);
}
}
}
// "ConcreteHandler"
// Request details
class Purchase
{
private int number;
private double amount;
private string purpose;
// Constructor
public Purchase(int number, double amount, string purpose)
{
this.number = number;
this.amount = amount;
this.purpose = purpose;
}
// Properties
public double Amount
{
get{ return amount; }
set{ amount = value; }
}
Version: 1.0
Side: 148
Project: Design Pattern
Output
Director Larry approved request# 2034
President Tammy approved request# 2035
Request# 2036 requires an executive meeting!
*&---------------------------------------------------------------------*
*& Report ZDP_CHAINOFRESP_REALWORLD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_chainofresp_realworld.
CLASS cl_abap_typedescr DEFINITION LOAD.
*----------------------------------------------------------------------*
* Global Data
*----------------------------------------------------------------------*
DATA: moff TYPE i
,slen TYPE i
,mlen TYPE i.
*----------------------------------------------------------------------*
* Macro ?get_class_name returns the class name of the class
* Importing &1 Any Class
* Exporting &2 The name of the Class &1
*----------------------------------------------------------------------*
DEFINE ?get_class_name.
&2 = cl_abap_classdescr=>get_class_name( &1 ).
find regex 'CLASS=' in &2 match offset moff match length mlen.
slen = moff + mlen.
shift &2 by slen places left.
END-OF-DEFINITION.
*----------------------------------------------------------------------*
* CLASS purchase DEFINITION
*----------------------------------------------------------------------*
Version: 1.0
Side: 149
Project: Design Pattern
*
*----------------------------------------------------------------------*
CLASS purchase DEFINITION.
PUBLIC SECTION.
METHODS:
constructor IMPORTING number TYPE i
amount TYPE f
purpose TYPE string
,get_property IMPORTING name TYPE string
RETURNING value(dref) TYPE REF TO data.
PRIVATE SECTION.
DATA:
number TYPE i
,amount TYPE f
,purpose TYPE string
.
METHOD get_property.
CASE name.
WHEN 'NUMBER'.
GET REFERENCE OF me->number INTO dref.
WHEN 'AMOUNT'.
GET REFERENCE OF me->amount INTO dref.
WHEN 'PURPOSE'.
GET REFERENCE OF me->purpose INTO dref.
ENDCASE.
ENDMETHOD. "get_property
*----------------------------------------------------------------------*
* CLASS approver DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS approver DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING name TYPE string
,setsuccessor IMPORTING successor TYPE REF TO approver
,processrequest ABSTRACT IMPORTING purchase TYPE REF TO purchase .
PROTECTED SECTION.
DATA: name TYPE string.
DATA: successor TYPE REF TO approver.
ENDCLASS. "approver DEFINITION
*----------------------------------------------------------------------*
Version: 1.0
Side: 150
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS Director DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS director DEFINITION INHERITING FROM approver.
PUBLIC SECTION.
METHODS:
processrequest REDEFINITION.
ENDCLASS. "Director DEFINITION
*----------------------------------------------------------------------*
* CLASS Director IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS director IMPLEMENTATION.
METHOD processrequest.
FIELD-SYMBOLS:
<fs_amount> TYPE f
,<fs_number> TYPE i.
?get_class_name me class_name.
*----------------------------------------------------------------------*
* CLASS VicePresident DEFINITION
*----------------------------------------------------------------------*
Version: 1.0
Side: 151
Project: Design Pattern
*
*----------------------------------------------------------------------*
CLASS vicepresident DEFINITION INHERITING FROM approver.
PUBLIC SECTION.
METHODS:
processrequest REDEFINITION.
ENDCLASS. "VicePresident DEFINITION
*----------------------------------------------------------------------*
* CLASS VicePresident IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS vicepresident IMPLEMENTATION.
METHOD processrequest.
FIELD-SYMBOLS:
<fs_amount> TYPE f
,<fs_number> TYPE i.
?get_class_name me class_name.
*----------------------------------------------------------------------*
* CLASS President DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS president DEFINITION INHERITING FROM approver.
PUBLIC SECTION.
METHODS:
processrequest REDEFINITION.
ENDCLASS. "President DEFINITION
*----------------------------------------------------------------------*
* CLASS President IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS president IMPLEMENTATION.
METHOD processrequest.
FIELD-SYMBOLS:
<fs_amount> TYPE f
Version: 1.0
Side: 152
Project: Design Pattern
,<fs_number> TYPE i.
?get_class_name me class_name.
*----------------------------------------------------------
* CLASS lcl_application DEFINITION
*----------------------------------------------------------
CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.
ENDCLASS. "lcl_application DEFINITION
*----------------------------------------------------------
* IMPLEMENTATION
*----------------------------------------------------------
CLASS lcl_application IMPLEMENTATION.
*----------------------------------------------------------
* LCL_APPLICATION->RUN().
*----------------------------------------------------------
METHOD run.
DATA:
exc_ref TYPE REF TO cx_root
,exc_text TYPE string.
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
*----------------------------------------------------------
* LCL_APPLICATION->CONSTRUCTOR().
Version: 1.0
Side: 153
Project: Design Pattern
larry->setsuccessor( sam ).
sam->setsuccessor( tammy ).
CREATE OBJECT p
EXPORTING number = 2034
amount = 350
purpose = 'Supplies'.
larry->processrequest( p ).
CREATE OBJECT p
EXPORTING number = 2035
amount = '32590.10'
purpose = 'Project X'.
larry->processrequest( p ).
CREATE OBJECT p
EXPORTING number = 2036
amount = '122100.00'
purpose = 'Project Y'.
larry->processrequest( p ).
ENDMETHOD. "constructor
START-OF-SELECTION.
lcl_application=>run( ).
2.3.2 Command
Encapsulate a command request as an object
2.3.2.1 Definition
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or
log requests, and support undoable operations.
Version: 1.0
Side: 154
Project: Design Pattern
2.3.2.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.
using System;
namespace DoFactory.GangOfFour.Command.Structural
{
class MainApp
{
static void Main()
Version: 1.0
Side: 155
Project: Design Pattern
{
// Create receiver, command, and invoker
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
// "Command"
// Constructor
public Command(Receiver receiver)
{
this.receiver = receiver;
}
// "ConcreteCommand"
// "Receiver"
class Receiver
{
public void Action()
{
Console.WriteLine("Called Receiver.Action()");
}
}
Version: 1.0
Side: 156
Project: Design Pattern
// "Invoker"
class Invoker
{
private Command command;
Output
Called Receiver.Action()
REPORT zdp_command_structural.
*----------------------------------------------------------------------*
* CLASS receiver DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS receiver DEFINITION.
PUBLIC SECTION.
METHODS:
action.
ENDCLASS. "receiver DEFINITION
*----------------------------------------------------------------------*
* CLASS receiver IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS receiver IMPLEMENTATION.
METHOD action.
WRITE: / 'Console.WriteLine(Called Receiver.Action()'.
ENDMETHOD. "action
Version: 1.0
Side: 157
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS command DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS command DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
constructor IMPORTING receiver TYPE REF TO receiver
,execute ABSTRACT.
PROTECTED SECTION.
DATA: receiver TYPE REF TO receiver.
ENDCLASS. "command DEFINITION
*----------------------------------------------------------------------*
* CLASS command IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS command IMPLEMENTATION.
METHOD constructor.
me->receiver = receiver.
ENDMETHOD. "constructor
ENDCLASS. "command IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS concretecommand DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecommand DEFINITION INHERITING FROM command.
PUBLIC SECTION.
METHODS:
execute REDEFINITION.
ENDCLASS. "concretecommand DEFINITION
*----------------------------------------------------------------------*
* CLASS concretecommand IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS concretecommand IMPLEMENTATION.
METHOD execute.
me->receiver->action( ).
ENDMETHOD. "execute
ENDCLASS. "concretecommand IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS invoker DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS invoker DEFINITION.
PUBLIC SECTION.
METHODS:
setcommand IMPORTING command TYPE REF TO command
,executecommand .
PRIVATE SECTION.
Version: 1.0
Side: 158
Project: Design Pattern
*----------------------------------------------------------
* CLASS lcl_application DEFINITION
*----------------------------------------------------------
CLASS lcl_application DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS: run.
METHODS: constructor.
PRIVATE SECTION.
CLASS-DATA: so_application TYPE REF TO lcl_application.
ENDCLASS. "lcl_application DEFINITION
*----------------------------------------------------------
* IMPLEMENTATION
*----------------------------------------------------------
CLASS lcl_application IMPLEMENTATION.
*----------------------------------------------------------
* LCL_APPLICATION->RUN().
*----------------------------------------------------------
METHOD run.
DATA:
exc_ref TYPE REF TO cx_root
,exc_text TYPE string.
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
*----------------------------------------------------------
* LCL_APPLICATION->CONSTRUCTOR().
* Use the constructor for instantiating internal objects,
* fields, tables and events.
*----------------------------------------------------------
METHOD constructor.
DATA:
receiver TYPE REF TO receiver
,command TYPE REF TO concretecommand
Version: 1.0
Side: 159
Project: Design Pattern
ENDMETHOD. "constructor
START-OF-SELECTION.
lcl_application=>run( ).
Output:
Program ZDP_COMMAND_STRUCTURAL
Console.WriteLine(Called Receiver.Action()
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Command.RealWorld
{
class MainApp
{
static void Main()
{
// Create user and let her compute
User user = new User();
user.Compute('+', 100);
user.Compute('-', 50);
user.Compute('*', 10);
user.Compute('/', 2);
// Undo 4 commands
user.Undo(4);
// Redo 3 commands
user.Redo(3);
Version: 1.0
Side: 160
Project: Design Pattern
// "Command"
// "ConcreteCommand"
// Constructor
public CalculatorCommand(Calculator calculator,
char @operator, int operand)
{
this.calculator = calculator;
this.@operator = @operator;
this.operand = operand;
}
Version: 1.0
Side: 161
Project: Design Pattern
{
case '+': undo = '-'; break;
case '-': undo = '+'; break;
case '*': undo = '/'; break;
case '/': undo = '*'; break;
default : undo = ' '; break;
}
return undo;
}
}
// "Receiver"
class Calculator
{
private int curr = 0;
// "Invoker"
class User
{
// Initializers
private Calculator calculator = new Calculator();
private ArrayList commands = new ArrayList();
Version: 1.0
Side: 162
Project: Design Pattern
Output
Current value = 100 (following + 100)
Current value = 50 (following - 50)
Current value = 500 (following * 10)
Current value = 250 (following / 2)
Version: 1.0
Side: 163
Project: Design Pattern
*&
*&
*&---------------------------------------------------------------------*
REPORT zdp_command_realworld.
*----------------------------------------------------------------------*
* CLASS command DEFINITION
*----------------------------------------------------------------------*
* An abstract class does not have implementations for abstract methods
*----------------------------------------------------------------------*
CLASS command DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
execute ABSTRACT
,unexecute ABSTRACT .
ENDCLASS. "command DEFINITION
*----------------------------------------------------------------------*
* CLASS calculator DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS calculator DEFINITION.
PUBLIC SECTION.
METHODS:
operation IMPORTING operator TYPE char1
operand TYPE i.
PRIVATE SECTION.
DATA: curr TYPE i VALUE 0.
ENDCLASS. "calculator DEFINITION
*----------------------------------------------------------------------*
* CLASS calculator IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS calculator IMPLEMENTATION.
METHOD operation.
CASE operator.
WHEN '+'.
curr = curr + operand.
WHEN '-'.
curr = curr - operand.
WHEN '*'.
curr = curr * operand.
WHEN '/'.
curr = curr / operand.
ENDCASE.
WRITE: / 'Current Value = ', curr, '(following', (1) operator, (3) operand, ')'.
ENDMETHOD. "operation
ENDCLASS. "calculator IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS calculatorcommand DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
Version: 1.0
Side: 164
Project: Design Pattern
*----------------------------------------------------------------------*
* CLASS calculatorcommand IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS calculatorcommand IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
me->calculator = calculator.
CREATE OBJECT me->_operand.
me->_operand->set( operand ).
CREATE OBJECT me->_operator.
me->_operator->set( operator ).
ENDMETHOD. "constructor
METHOD operator.
me->_operator->set( operator ).
ENDMETHOD. "operator
METHOD operand.
me->_operand->set( operand ).
ENDMETHOD. "operand
METHOD execute.
DATA: l_operator TYPE char1
,l_operand TYPE integer.
l_operator = _operator->get( ).
l_operand = _operand->get( ).
me->calculator->operation( operator = l_operator
operand = l_operand ).
ENDMETHOD. "execute
METHOD unexecute.
DATA: l_operand TYPE integer
,l_operator TYPE char1 .
l_operand = _operand->get( ).
Version: 1.0
Side: 165
Project: Design Pattern
l_operator = _operator->get( ).
l_operator = me->undo( l_operator ).
METHOD undo.
CASE operator.
WHEN '+'. newoperator = '-'.
WHEN '-'. newoperator = '+'.
WHEN '*'. newoperator = '/'.
WHEN '/'. newoperator = '*'.
WHEN OTHERS. newoperator = ' '.
ENDCASE.
ENDMETHOD. "undo
*----------------------------------------------------------------------*
* CLASS user DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS user DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
,redo IMPORTING levels TYPE integer
,undo IMPORTING levels TYPE integer
,compute IMPORTING operator TYPE char1
operand TYPE integer
.
PRIVATE SECTION.
DATA:
calculator TYPE REF TO calculator
,commands TYPE TABLE OF REF TO command
,current TYPE integer VALUE 0
,command TYPE REF TO calculatorcommand
.
*----------------------------------------------------------------------*
* CLASS user IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS user IMPLEMENTATION.
METHOD constructor.
CREATE OBJECT calculator.
ENDMETHOD. "constructor
METHOD redo.
DATA: i TYPE integer VALUE 1
,count TYPE i
,l_command TYPE REF TO command
,my_command TYPE REF TO calculatorcommand
Version: 1.0
Side: 166
Project: Design Pattern
.
DESCRIBE TABLE commands LINES count.
SUBTRACT 1 FROM count.
WRITE: /, / '----Redo levels ', levels.
* perform redo operations
WHILE i <= levels.
IF current <= count.
ADD 1 TO current.
READ TABLE commands INDEX current INTO l_command.
my_command ?= l_command.
l_command->execute( ).
ENDIF.
ADD 1 TO i.
ENDWHILE.
ENDMETHOD. "redo
"redo
METHOD undo.
DATA: i TYPE integer VALUE 0
,l_command TYPE REF TO command
,my_command TYPE REF TO calculatorcommand
.
WRITE: /,/ '----Undo levels ', levels.
* perform redo operations
WHILE i < levels.
IF current > 0.
READ TABLE commands INDEX current INTO l_command .
SUBTRACT 1 FROM current.
my_command ?= l_command.
l_command->unexecute( ).
ENDIF.
ADD 1 TO i.
ENDWHILE.
ENDMETHOD. "undo
METHOD compute.
* // Create command operation and execute it
CREATE OBJECT command EXPORTING calculator = calculator
operator = operator
operand = operand.
me->command->execute( ).
APPEND me->command TO commands.
ADD 1 TO current.
ENDMETHOD. "compute
*----------------------------------------------------------
* IMPLEMENTATION
*----------------------------------------------------------
Version: 1.0
Side: 167
Project: Design Pattern
*----------------------------------------------------------
* LCL_APPLICATION->RUN().
*----------------------------------------------------------
METHOD run.
DATA:
exc_ref TYPE REF TO cx_root
,exc_text TYPE string.
IF lcl_application=>so_application IS INITIAL.
TRY.
CREATE OBJECT lcl_application=>so_application.
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE 'I'.
ENDTRY.
ENDIF.
ENDMETHOD. "run
METHOD constructor.
DATA: user TYPE REF TO user.
super->constructor( ).
CREATE OBJECT user.
ENDMETHOD. "constructor
ENDCLASS. "lcl_application IMPLEMENTATION
START-OF-SELECTION.
lcl_application=>run( ).
Report ZDP_COMMAND_REALWORLD
Undo levels 4
Current Value = 500 (following * 2 )
Current Value = 50 (following / 10 )
Current Value = 100 (following + 50 )
Current Value = 0 (following - 100 )
Redo levels 3
Current Value = 100 (following + 100 )
Current Value = 50 (following - 50 )
Current Value = 500 (following * 10 )
Version: 1.0
Side: 168
Project: Design Pattern
2.3.3 Interpreter
A way to include language elements in a program
2.3.3.1 Definition
Given a language, define a representation for its grammar along with an interpreter that uses the
representation to interpret sentences in the language
2.3.3.3 Participants
The classes and/or objects participating in this pattern are:
• AbstractExpression (Expression)
o declares an interface for executing an operation
• TerminalExpression ( ThousandExpression, HundredExpression, TenExpression,
OneExpression )
o implements an Interpret operation associated with terminal symbols in the grammar.
o an instance is required for every terminal symbol in the sentence.
• NonterminalExpression ( not used )
o one such class is required for every rule R ::= R1R2...Rn in the grammar
o maintains instance variables of type AbstractExpression for each of the symbols R1 through
Rn.
o implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically
calls itself recursively on the variables representing R1 through Rn.
• Context (Context)
o contains information that is global to the interpreter
• Client (InterpreterApp)
o builds (or is given) an abstract syntax tree representing a particular sentence in the
language that the grammar defines. The abstract syntax tree is assembled from instances of
the NonterminalExpression and TerminalExpression classes
o invokes the Interpret operation
Version: 1.0
Side: 169
Project: Design Pattern
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Interpreter.Structural
{
class MainApp
{
static void Main()
{
Context context = new Context();
// Usually a tree
ArrayList list = new ArrayList();
// Interpret
foreach (AbstractExpression exp in list)
{
exp.Interpret(context);
}
// "Context"
class Context
{
}
// "AbstractExpression"
// "TerminalExpression"
Version: 1.0
Side: 170
Project: Design Pattern
{
public override void Interpret(Context context)
{
Console.WriteLine("Called Terminal.Interpret()");
}
}
// "NonterminalExpression"
Output
Called Terminal.Interpret()
Called Nonterminal.Interpret()
Called Terminal.Interpret()
Called Terminal.Interpret()
This real-world code demonstrates the Interpreter pattern which is used to convert a Roman numeral to a
decimal.
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Interpreter.RealWorld
{
class MainApp
{
static void Main()
{
string roman = "MCMXXVIII";
Context context = new Context(roman);
// Interpret
foreach (Expression exp in tree)
{
Version: 1.0
Side: 171
Project: Design Pattern
exp.Interpret(context);
}
Console.WriteLine("{0} = {1}",
roman, context.Output);
// "Context"
class Context
{
private string input;
private int output;
// Constructor
public Context(string input)
{
this.input = input;
}
// Properties
public string Input
{
get{ return input; }
set{ input = value; }
}
// "AbstractExpression"
if (context.Input.StartsWith(Nine()))
{
context.Output += (9 * Multiplier());
context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(Four()))
{
context.Output += (4 * Multiplier());
context.Input = context.Input.Substring(2);
Version: 1.0
Side: 172
Project: Design Pattern
}
else if (context.Input.StartsWith(Five()))
{
context.Output += (5 * Multiplier());
context.Input = context.Input.Substring(1);
}
while (context.Input.StartsWith(One()))
{
context.Output += (1 * Multiplier());
context.Input = context.Input.Substring(1);
}
}
Version: 1.0
Side: 173
Project: Design Pattern
// One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
// "TerminalExpression"
Output
MCMXXVIII = 1928
2.3.4 Iterator
Sequentially access the elements of a collection
2.3.4.1 Definition
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying
representation.
2.3.4.3 Participants
The classes and/or objects participating in this pattern are:
• Iterator (AbstractIterator)
o defines an interface for accessing and traversing elements.
• ConcreteIterator (Iterator)
Version: 1.0
Side: 174
Project: Design Pattern
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Iterator.Structural
{
class MainApp
{
static void Main()
{
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "Item A";
a[1] = "Item B";
a[2] = "Item C";
a[3] = "Item D";
// "Aggregate"
Version: 1.0
Side: 175
Project: Design Pattern
{
public abstract Iterator CreateIterator();
}
// "ConcreteAggregate"
// Property
public int Count
{
get{ return items.Count; }
}
// Indexer
public object this[int index]
{
get{ return items[index]; }
set{ items.Insert(index, value); }
}
}
// "Iterator"
// "ConcreteIterator"
// Constructor
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}
Version: 1.0
Side: 176
Project: Design Pattern
return ret;
}
Output
Iterating over collection:
Item A
Item B
Item C
Item D
This real-world code demonstrates the Iterator pattern which is used to iterate over a
collection of items and skip a specific number of items each iteration.
// Iterator pattern -- Real World example
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Iterator.RealWorld
{
class MainApp
{
static void Main()
{
// Build a collection
Collection collection = new Collection();
collection[0] = new Item("Item 0");
collection[1] = new Item("Item 1");
collection[2] = new Item("Item 2");
collection[3] = new Item("Item 3");
collection[4] = new Item("Item 4");
Version: 1.0
Side: 177
Project: Design Pattern
// Create iterator
Iterator iterator = new Iterator(collection);
class Item
{
string name;
// Constructor
public Item(string name)
{
this.name = name;
}
// Property
public string Name
{
get{ return name; }
}
}
// "Aggregate"
interface IAbstractCollection
{
Iterator CreateIterator();
}
// "ConcreteAggregate"
Version: 1.0
Side: 178
Project: Design Pattern
// Property
public int Count
{
get{ return items.Count; }
}
// Indexer
public object this[int index]
{
get{ return items[index]; }
set{ items.Add(value); }
}
}
// "Iterator"
interface IAbstractIterator
{
Item First();
Item Next();
bool IsDone{ get; }
Item CurrentItem{ get; }
}
// "ConcreteIterator"
// Constructor
public Iterator(Collection collection)
{
this.collection = collection;
}
Version: 1.0
Side: 179
Project: Design Pattern
// Properties
public int Step
{
get{ return step; }
set{ step = value; }
}
Output
Iterating over collection:
Item 0
Item 2
Item 4
Item 6
Item 8
2.3.5 Mediator
Defines simplified communication between classes
2.3.5.1 Definition
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by
keeping objects from referring to each other explicitly, and it lets you vary their interaction independently
Version: 1.0
Side: 180
Project: Design Pattern
2.3.5.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
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Mediator.Structural
{
class MainApp
{
static void Main()
{
ConcreteMediator m = new ConcreteMediator();
Version: 1.0
Side: 181
Project: Design Pattern
m.Colleague1 = c1;
m.Colleague2 = c2;
// "Mediator"
// "ConcreteMediator"
// "Colleague"
Version: 1.0
Side: 182
Project: Design Pattern
{
protected Mediator mediator;
// Constructor
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
}
// "ConcreteColleague1"
// "ConcreteColleague2"
Output
Version: 1.0
Side: 183
Project: Design Pattern
This real-world code demonstrates the Mediator pattern facilitating loosely coupled
communication between different Participants registering with a Chatroom. The Chatroom
is the central hub through which all communication takes place. At this point only one-to-
one communication is implemented in the Chatroom, but would be trivial to change to one-
to-many.
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Mediator.RealWorld
{
class MainApp
{
static void Main()
{
// Create chatroom
Chatroom chatroom = new Chatroom();
chatroom.Register(George);
chatroom.Register(Paul);
chatroom.Register(Ringo);
chatroom.Register(John);
chatroom.Register(Yoko);
// Chatting participants
Yoko.Send ("John", "Hi John!");
Paul.Send ("Ringo", "All you need is love");
Ringo.Send("George", "My sweet Lord");
Paul.Send ("John", "Can't buy me love");
John.Send ("Yoko", "My sweet love") ;
// "Mediator"
Version: 1.0
Side: 184
Project: Design Pattern
{
public abstract void Register(Participant participant);
public abstract void Send(
string from, string to, string message);
}
// "ConcreteMediator"
participant.Chatroom = this;
}
// "AbstractColleague"
class Participant
{
private Chatroom chatroom;
private string name;
// Constructor
public Participant(string name)
{
this.name = name;
}
// Properties
public string Name
{
get{ return name; }
}
Version: 1.0
Side: 185
Project: Design Pattern
//" ConcreteColleague1"
//" ConcreteColleague2"
Output
To a Beatle: Yoko to John: 'Hi John!'
To a Beatle: Paul to Ringo: 'All you need is love'
To a Beatle: Ringo to George: 'My sweet Lord'
To a Beatle: Paul to John: 'Can't buy me love'
To a non-Beatle: John to Yoko: 'My sweet love'
Version: 1.0
Side: 186
Project: Design Pattern
2.3.6 Memento
Capture and restore an object's internal state
2.3.6.1 Definition
Without violating encapsulation, capture and externalize an object's internal state so that the object can be
restored to this state later.
2.3.6.3 Participants
The classes and/or objects participating in this pattern are:
• Memento (Memento)
o stores internal state of the Originator object. The memento may store as much or as little of
the originator's internal state as necessary at its originator's discretion.
o protect against access by objects of other than the originator. Mementos have effectively two
interfaces. Caretaker sees a narrow interface to the Memento -- it can only pass the
memento to the other objects. Originator, in contrast, sees a wide interface, one that lets it
access all the data necessary to restore itself to its previous state. Ideally, only the originator
that produces the memento would be permitted to access the memento's internal state.
• Originator (SalesProspect)
o creates a memento containing a snapshot of its current internal state.
o uses the memento to restore its internal state
• Caretaker (Caretaker)
o is responsible for the memento's safekeeping
o never operates on or examines the contents of a memento.
using System;
namespace DoFactory.GangOfFour.Memento.Structural
{
Version: 1.0
Side: 187
Project: Design Pattern
class MainApp
{
static void Main()
{
Originator o = new Originator();
o.State = "On";
// "Originator"
class Originator
{
private string state;
// Property
public string State
{
get{ return state; }
set
{
state = value;
Console.WriteLine("State = " + state);
}
}
// "Memento"
Version: 1.0
Side: 188
Project: Design Pattern
class Memento
{
private string state;
// Constructor
public Memento(string state)
{
this.state = state;
}
// Property
public string State
{
get{ return state; }
}
}
// "Caretaker"
class Caretaker
{
private Memento memento;
// Property
public Memento Memento
{
set{ memento = value; }
get{ return memento; }
}
}
}
Output
State = On
State = Off
Restoring state:
State = On
This real-world code demonstrates the Memento pattern which temporarily saves and then
restores the SalesProspect's internal state.
// Memento pattern -- Real World example
using System;
namespace DoFactory.GangOfFour.Memento.RealWorld
{
class MainApp
{
static void Main()
{
SalesProspect s = new SalesProspect();
Version: 1.0
Side: 189
Project: Design Pattern
// "Originator"
class SalesProspect
{
private string name;
private string phone;
private double budget;
// Properties
public string Name
{
get{ return name; }
set
{
name = value;
Console.WriteLine("Name: " + name);
}
}
Version: 1.0
Side: 190
Project: Design Pattern
// "Memento"
class Memento
{
private string name;
private string phone;
private double budget;
// Constructor
public Memento(string name, string phone, double budget)
{
this.name = name;
this.phone = phone;
this.budget = budget;
}
// Properties
public string Name
{
get{ return name; }
set{ name = value; }
}
// "Caretaker"
Version: 1.0
Side: 191
Project: Design Pattern
class ProspectMemory
{
private Memento memento;
// Property
public Memento Memento
{
set{ memento = value; }
get{ return memento; }
}
}
}
Output
Name: Noel van Halen
Phone: (412) 256-0990
Budget: 25000
Saving state --
Restoring state --
2.3.7 Observer
A way of notifying change to a number of classes
2.3.7.1 Definition
Define a one-to-many dependency between objects so that when one object changes state, all its
dependents are notified and updated automatically.
Version: 1.0
Side: 192
Project: Design Pattern
2.3.7.3 Participants
The classes and/or objects participating in this pattern are:
• Subject (Stock)
o knows its observers. Any number of Observer objects may observe a subject
o provides an interface for attaching and detaching Observer objects.
• ConcreteSubject (IBM)
o stores state of interest to ConcreteObserver
o sends a notification to its observers when its state changes
• Observer (IInvestor)
o defines an updating interface for objects that should be notified of changes in a subject.
• ConcreteObserver (Investor)
o maintains a reference to a ConcreteSubject object
o stores state that should stay consistent with the subject's
o implements the Observer updating interface to keep its state consistent with the subject's
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Observer.Structural
{
Version: 1.0
Side: 193
Project: Design Pattern
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"));
// "Subject"
// "ConcreteSubject"
// Property
public string SubjectState
Version: 1.0
Side: 194
Project: Design Pattern
{
get{ return subjectState; }
set{ subjectState = value; }
}
}
// "Observer"
// "ConcreteObserver"
// Constructor
public ConcreteObserver(
ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}
// 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.
Version: 1.0
Side: 195
Project: Design Pattern
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Observer.RealWorld
{
class MainApp
{
static void Main()
{
// Create investors
Investor s = new Investor("Sorros");
Investor b = new Investor("Berkshire");
// "Subject"
// Constructor
public Stock(string symbol, double price)
{
this.symbol = symbol;
this.price = price;
}
Version: 1.0
Side: 196
Project: Design Pattern
// Properties
public double Price
{
get{ return price; }
set
{
price = value;
Notify();
}
}
// "ConcreteSubject"
// "Observer"
interface IInvestor
{
void Update(Stock stock);
}
// "ConcreteObserver"
// Constructor
public Investor(string name)
{
Version: 1.0
Side: 197
Project: Design Pattern
this.name = name;
}
// Property
public Stock Stock
{
get{ return stock; }
set{ stock = value; }
}
}
}
Output
Notified Sorros of IBM's change to $120.10
Notified Berkshire of IBM's change to $120.10
2.3.8 State
Alter an object's behavior when its state changes
2.3.8.1 Definition
Allow an object to alter its behavior when its internal state changes. The object will appear to change its
class
Version: 1.0
Side: 198
Project: Design Pattern
2.3.8.3 Participants
The classes and/or objects participating in this pattern are:
• Context (Account)
o defines the interface of interest to clients
o maintains an instance of a ConcreteState subclass that defines the current state.
• State (State)
o defines an interface for encapsulating the behavior associated with a particular state of the
Context.
• Concrete State (RedState, SilverState, GoldState)
o each subclass implements a behavior associated with a state of Context
This structural code demonstrates the State pattern which allows an object to behave
differently depending on its internal state. The difference in behavior is delegated to
objects that represent this state.
using System;
namespace DoFactory.GangOfFour.State.Structural
{
class MainApp
{
static void Main()
{
// Setup context in a state
Context c = new Context(new ConcreteStateA());
// "State"
Version: 1.0
Side: 199
Project: Design Pattern
// "ConcreteStateA"
// "ConcreteStateB"
// "Context"
class Context
{
private State state;
// Constructor
public Context(State state)
{
this.State = state;
}
// Property
public State State
{
get{ return state; }
set
{
state = value;
Console.WriteLine("State: " +
state.GetType().Name);
}
}
Output
State: ConcreteStateA
State: ConcreteStateB
State: ConcreteStateA
Version: 1.0
Side: 200
Project: Design Pattern
State: ConcreteStateB
State: ConcreteStateA
This real-world code demonstrates the State pattern which allows an Account to behave
differently depending on its balance. The difference in behavior is delegated to State
objects called RedState, SilverState and GoldState. These states represent overdrawn
accounts, starter accounts, and accounts in good standing.
using System;
namespace DoFactory.GangOfFour.State.RealWorld
{
class MainApp
{
static void Main()
{
// Open a new account
Account account = new Account("Jim Johnson");
// "State"
// Properties
public Account Account
{
get{ return account; }
set{ account = value; }
}
Version: 1.0
Side: 201
Project: Design Pattern
// "ConcreteState"
// Account is overdrawn
// Constructor
public RedState(State state)
{
this.balance = state.Balance;
this.account = state.Account;
Initialize();
}
Version: 1.0
Side: 202
Project: Design Pattern
{
account.State = new SilverState(this);
}
}
}
// "ConcreteState"
Version: 1.0
Side: 203
Project: Design Pattern
// "ConcreteState"
Version: 1.0
Side: 204
Project: Design Pattern
// "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; }
}
Version: 1.0
Side: 205
Project: Design Pattern
Output
Deposited $500.00 ---
Balance = $500.00
Status = SilverState
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.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.
using System;
namespace DoFactory.GangOfFour.Strategy.Structural
{
class MainApp
{
static void Main()
{
Context context;
Version: 1.0
Side: 207
Project: Design Pattern
// "Strategy"
// "ConcreteStrategyA"
// "ConcreteStrategyB"
// "ConcreteStrategyC"
// "Context"
class Context
{
Strategy strategy;
Version: 1.0
Side: 208
Project: Design Pattern
// Constructor
public Context(Strategy strategy)
{
this.strategy = strategy;
}
Output
Called ConcreteStrategyA.AlgorithmInterface()
Called ConcreteStrategyB.AlgorithmInterface()
Called ConcreteStrategyC.AlgorithmInterface()
This real-world code demonstrates the Strategy pattern which encapsulates sorting
algorithms in the form of sorting objects. This allows clients to dynamically change sorting
strategies including Quicksort, Shellsort, and Mergesort.
// Strategy pattern -- Real World example
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Strategy.RealWorld
{
class MainApp
{
static void Main()
{
// Two contexts following different strategies
SortedList studentRecords = new SortedList();
studentRecords.Add("Samual");
studentRecords.Add("Jimmy");
studentRecords.Add("Sandra");
studentRecords.Add("Vivek");
studentRecords.Add("Anna");
studentRecords.SetSortStrategy(new QuickSort());
studentRecords.Sort();
studentRecords.SetSortStrategy(new ShellSort());
studentRecords.Sort();
studentRecords.SetSortStrategy(new MergeSort());
studentRecords.Sort();
Version: 1.0
Side: 209
Project: Design Pattern
// "Strategy"
// "ConcreteStrategy"
// "ConcreteStrategy"
// "ConcreteStrategy"
// "Context"
class SortedList
{
private ArrayList list = new ArrayList();
private SortStrategy sortstrategy;
Version: 1.0
Side: 210
Project: Design Pattern
// Display results
foreach (string name in list)
{
Console.WriteLine(" " + name);
}
Console.WriteLine();
}
}
}
Output
QuickSorted list
Anna
Jimmy
Samual
Sandra
Vivek
ShellSorted list
Anna
Jimmy
Samual
Sandra
Vivek
MergeSorted list
Anna
Jimmy
Samual
Sandra
Vivek
2.3.10.1 Definition
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method
lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure
Version: 1.0
Side: 211
Project: Design Pattern
2.3.10.3 Participants
The classes and/or objects participating in this pattern are:
• AbstractClass (DataObject)
o defines abstract primitive operations that concrete subclasses define to implement steps of
an algorithm
o implements a template method defining the skeleton of an algorithm. The template method
calls primitive operations as well as operations defined in AbstractClass or those of other
objects.
• ConcreteClass (CustomerDataObject)
o implements the primitive operations ot carry out subclass-specific steps of the algorithm
using System;
namespace DoFactory.GangOfFour.Template.Structural
{
class MainApp
{
static void Main()
{
AbstractClass c;
Version: 1.0
Side: 212
Project: Design Pattern
c = new ConcreteClassA();
c.TemplateMethod();
c = new ConcreteClassB();
c.TemplateMethod();
// "AbstractClass"
// "ConcreteClass"
Output
Version: 1.0
Side: 213
Project: Design Pattern
ConcreteClassA.PrimitiveOperation1()
ConcreteClassA.PrimitiveOperation2()
This real-world code demonstrates a Template method named Run() which provides a
skeleton calling sequence of methods. Implementation of these steps are deferred to the
CustomerDataObject subclass which implements the Connect, Select, Process, and
Disconnect methods.
// Template pattern -- Real World example
using System;
using System.Data;
using System.Data.OleDb;
namespace DoFactory.GangOfFour.Template.RealWorld
{
class MainApp
{
static void Main()
{
DataAccessObject dao;
// "AbstractClass"
Version: 1.0
Side: 214
Project: Design Pattern
{
connectionString = "";
}
// "ConcreteClass"
Version: 1.0
Side: 215
Project: Design Pattern
Output
Categories ----
Beverages
Condiments
Confections
Dairy Products
Grains/Cereals
Meat/Poultry
Produce
Seafood
Products ----
Chai
Chang
Aniseed Syrup
Chef Anton's Cajun Seasoning
Chef Anton's Gumbo Mix
Grandma's Boysenberry Spread
Uncle Bob's Organic Dried Pears
Northwoods Cranberry Sauce
Mishi Kobe Niku
2.3.11 Visitor
Defines a new operation to a class without change
2.3.11.1 Definition
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new
operation without changing the classes of the elements on which it operates.
Version: 1.0
Side: 216
Project: Design Pattern
2.3.11.3 Participants
The classes and/or objects participating in this pattern are:
• Visitor (Visitor)
o declares a Visit operation for each class of ConcreteElement in the object structure. The
operation's name and signature identifies the class that sends the Visit request to the visitor.
That lets the visitor determine the concrete class of the element being visited. Then the
visitor can access the elements directly through its particular interface
• ConcreteVisitor (IncomeVisitor, VacationVisitor)
o implements each operation declared by Visitor. Each operation implements a fragment of
the algorithm defined for the corresponding class or object in the structure. ConcreteVisitor
provides the context for the algorithm and stores its local state. This state often accumulates
results during the traversal of the structure.
• Element (Element)
o defines an Accept operation that takes a visitor as an argument.
• ConcreteElement (Employee)
Version: 1.0
Side: 217
Project: Design Pattern
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Visitor.Structural
{
class MainApp
{
static void Main()
{
// Setup structure
ObjectStructure o = new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());
// "Visitor"
Version: 1.0
Side: 218
Project: Design Pattern
// "ConcreteVisitor1"
// "ConcreteVisitor2"
// "Element"
// "ConcreteElementA"
Version: 1.0
Side: 219
Project: Design Pattern
}
}
// "ConcreteElementB"
// "ObjectStructure"
class ObjectStructure
{
private ArrayList elements = new ArrayList();
Output
ConcreteElementA visited by ConcreteVisitor1
ConcreteElementB visited by ConcreteVisitor1
ConcreteElementA visited by ConcreteVisitor2
ConcreteElementB visited by ConcreteVisitor2
This real-world code demonstrates the Visitor pattern in which two objects traverse a list of
Employees and performs the same operation on each Employee. The two visitor objects
define different operations -- one adjusts vacation days and the other income.
Version: 1.0
Side: 220
Project: Design Pattern
using System;
using System.Collections;
namespace DoFactory.GangOfFour.Visitor.RealWorld
{
class MainApp
{
static void Main()
{
// Setup employee collection
Employees e = new Employees();
e.Attach(new Clerk());
e.Attach(new Director());
e.Attach(new President());
// "Visitor"
interface IVisitor
{
void Visit(Element element);
}
// "ConcreteVisitor1"
// "ConcreteVisitor2"
Version: 1.0
Side: 221
Project: Design Pattern
{
Employee employee = element as Employee;
// "Element"
// "ConcreteElement"
// Constructor
public Employee(string name, double income,
int vacationDays)
{
this.name = name;
this.income = income;
this.vacationDays = vacationDays;
Version: 1.0
Side: 222
Project: Design Pattern
// Properties
public string Name
{
get{ return name; }
set{ name = value; }
}
// "ObjectStructure"
class Employees
{
private ArrayList employees = new ArrayList();
Output
Version: 1.0
Side: 223
Project: Design Pattern
Version: 1.0
Side: 224