Download as pdf or txt
Download as pdf or txt
You are on page 1of 41

OOD and C++

UML, Design & Patterns


Intro
Concept: Providing generic design prototypes for
common problems.
First proposed by C. Alexander in the 70's
Popularised by the Gang of four's book (Design
Patterns: Elements of Reusable Object
Oriented Software).
+ Helps solving quickly complex problems
+ Helps design readability (common structures)
- Can lead to bloated design if use
undiscriminately.
Plan

UML Diagrams

Function objects (Functors)

Creational Patterns

Structural Patterns

Main source:
Design Patterns: Elements of Reusable Object
Oriented Software. Gamma, E., Helm, R.,
Johnson, R. and Vlissides, J. (so-called Gang
of Four)
UML: Class Diagram
ClassName top: class name
dataMember1 : type1
dataMember2 : type2 middle: data members
method1( parameter : type3 )
bottom: methods

ClassName
visibility is denoted by a
# dataMember1 : type1 prefix:
- dataMember2 : type2 = 0
+ method1( parameter : type3 )
+ for public
# for protected
- for private
UML: Generalisation (or inheritance)
AbstractShape Pure virtual methods
# position : int[2]
# color : char[3] are written in italic
+ draw( display : BaseDisplay & )
Inheritance is denoted
with an hollow
triangle pointing at
CircleShape the parent class.
- radius : int

+ draw( display : BaseDisplay & )


UML: Composition
AbstractShape Definition
1
# position : int[2] 0..*
# color : char[3] - listOfShapes
+ draw( display : BaseDisplay & ) + draw( display : BaseDisplay & )

Composition means that one class contains another:


when the container class is destructed, the contained
one is destructed too.
Represented by a filled diamond on the container side
Both sides of the line can specify the number of objects
in the relation: 0, 1, 0..*, 1..*, where * is any number.
Then name of the variable is also specified under the
line (eg, listOfShapes)
UML: Aggregation
ComplexShape 0..* 1 Definition

- definition
+ draw( display : BaseDisplay & ) + draw( display : BaseDisplay & )

Aggregation means that one class


contains a link (eg, pointer or
reference) to another: when the
container class is destructed, the
linked object remains.
Represented by a hollow diamond on
the container side
Function Objects (Functors)
Sometimes a function is the parameter for
another (eg, the sort and for_each functions in
the STL)
In C, this is handled by function pointers.
double
double compute_sum(
void
compute_sum( double
main( void ){
double (*funcp)(double),
(*funcp)(double), double
double lo,
lo, double
double hi
hi );
);
void main( void ){
double
double (*fp)(double);
(*fp)(double);
fp = sin;
fp = sin;
cout
cout <<<< compute_sum(
compute_sum( fp,
fp, 0.0,
0.0, 1.0
1.0 )) <<
<< endl;
endl;
fp
fp == cos;
cos;
cout
cout <<<< compute_sum(
compute_sum( fp,
fp, 0.0,
0.0, 1.0
1.0 )) <<
<< endl;
endl;
cout
cout <<<< compute_sum(
compute_sum( tan,
tan, 0.0,
0.0, 1.0
1.0 )) <<
<< endl;
endl;
}}

problem: poor syntax(!), and little safety.


Function Objects (Functors)
In C++, you can also create Function Objects.

class
class MyFunc
MyFunc {{
public:
public:
double
double operator()(double);
operator()(double);
};
};
double
double compute_sum(
compute_sum( const
const MyFunc
MyFunc &,
&, double
double lo,
lo, double
double hi);
hi);
void
void main(void){
main(void){
cout
cout <<
<< compute_sum(
compute_sum( MyFunc(),
MyFunc(), 0.0,
0.0, 1.0
1.0 )) <<
<< endl;
endl;
}}
Function Objects (Functors)
Advantage: you can control the allowed functions
using inheritance:
MyFunc

+ operator()( x : double )

SqrFunc PowerFunc
- p : double

+ operator()( x : double ) + operator()( x : double )


class
class MyFunc
MyFunc {{
public:
public:
};
};
Function Objects (Functors)
virtual
virtual double
double operator()(double)
operator()(double) const
const == 0;
0;

class
class SqrFunc
SqrFunc :: public
public MyFunc
MyFunc {{
public:
Advantage: you can control the allowed functions
public:
double
double operator()(double
operator()(double x)x) const
const {{
using inheritance:
}}
return
return x*x;
x*x;
};
};
class
class PowerFunc
PowerFunc :: public
public MyFunc
MyFunc {{
double
double p;
p;
public:
public:
PowerFunc(double
PowerFunc(double power)
power) :: p(power)
p(power) {}{}
double
double operator()(double
operator()(double x)x) const
const {{
return
return pow(x,p);
pow(x,p);
}}
};
};
double
double compute_sum(
compute_sum( const
const MyFunc
MyFunc &f,
&f, double
double lo,
lo, double
double hi);
hi);
int
int main(void){
main(void){
cout
cout <<
<< compute_sum(
compute_sum( SqrFunc(),
SqrFunc(), 0.0,
0.0, 1.0
1.0 )) <<
<< endl;
endl;
cout
cout <<
<< compute_sum(
compute_sum( PowerFunc(3.0),
PowerFunc(3.0), 0.0,
0.0, 1.0
1.0 )) <<
<< endl;
endl;
}}
Function Objects
Allow to restrict parameters to a family of
functions
Allow to pass extra parameters to the function in
the object constructor
You can use either function pointer or function
objects with the STL algo. (eg, sort, for_each).
Creational Patterns
Creational Patterns
Problem: Your code need to handle different
implementation of an abstract class, depending
on context. How do you create these objects
on the fly?

Here are three approaches to this problem:


Abstract Factory handle families of objects.
Factory Method hide polymorphism under
common interface
Prototype create objects by copying from a
dictionary of prototype objects.
Abstract Factory

Motivation: Provide a common interface for


creating families of related or dependent
objects.

Example: you have a video game that can


display characters and scenery either in night
or day time. An abstract factory will be an
abstract class which provides methods for
creating the correct descendants of each
abstract class.
Abstract Factory

Source: Design Patterns: Elements of Reusable Object Oriented Software.


Gamma, E., Helm, R., Johnson, R. and Vlissides, J. (so-called Gang of Four)
Example: Mario bros (I know...)
Game
AbstractFactory
Mario
+ draw()
+ createMario()
+ createLuigi()
+ draw()

NightFactory DayFactory NightMario DayMario

+ createMario() + createMario()
+ createLuigi() + draw() + draw()
+ createLuigi()
Abstract Factory

Symmetry of
hierarchies between
Factory & Products

Easy to switch
product families (here
from *1 to *2)

Consistency amongst
products.

Hard to add new kind


of products (need to
change
AbstractFactory!)
Factory Method

Motivation: define an interface for creating an


object, but let subclasses decide which one.

Hide the object creation behind a common


abstract interface.

Example: If you consider your operating


system's desktop, it has a default behaviour
that associates documents type and
applications, such that when you create a new
document under MS Word, a text document is
created.
Factory Method

Source: Design Patterns: Elements of Reusable Object Oriented Software.


Gamma, E., Helm, R., Johnson, R. and Vlissides, J. (so-called Gang of Four)
Example: documents & apps
Document
0..* 1 Application

+ open()
+ close() - documentsOpen
+ save() + createDocument()
+ newDocument() Document *doc;
doc = createDocument();
doc->open();

DOCX MS Word

creates
+
createDocume
nt()
Factory Method

Useful when you


have parallel
hierarchies (eg, a
shape hierarchy with
a separate
shapeReader
hierarchy).

Your code only


interacts with the
abstract interface.
Prototype

Motivation: Objects are created by copying a


prototypical instance derived from a common
base class.

Example: this is used in the design proposed


for the assignment. There, all valid shapes are
stored in a dictionary, and copied (using
clone()) when a draw statement is found.
Then the instance's parameters are read from
the file.
Prototype

Source: Design Patterns: Elements of Reusable Object Oriented Software.


Gamma, E., Helm, R., Johnson, R. and Vlissides, J. (so-called Gang of Four)
Example: Assignment design
AbstractShape World
0..* 1
# position : int[2]
# color : char[3]
+ draw( display : BaseDisplay & ) + dictionary
+ clone() : AbstractShape *

CircleShape
- radius : int
+ draw( display : BaseDisplay & )
+ clone() : AbstractShape *
Prototype

Allow to add and


remove products at
run-time

Specify new objects


by varying value (eg,
pointer to definition)

drawback: all
subclasses need to
implement clone()
Structural Patterns
Structural Patterns
How class & objects are composed to form
larger structure.
Simple example would be, eg, multiple
inheritance.
Patterns discussed:
Adapter how to integrate disparate designs
Composite recurrence.
(Decorator allow to add functionalities on the fly.)
Adapter
Motivation: You want to integrate an object in
your code, but its interface is incompatible. An
adapter class works as a translator between
the two designs.
Typical example: you need to do some
complicated video encoding, and you have
found a library that does it, but the interface for
their video objects is different from your
program...
Adapter
A) Class Adapter

B) Object Adapter

Source: Design Patterns: Elements of Reusable Object Oriented Software.


Gamma, E., Helm, R., Johnson, R. and Vlissides, J. (so-called Gang of Four)
Adapter example: Video processing
Video QuicktimeVideo

+ open() + OpenVideo()
+ close() + CloseVideo()
+ play() + PlayVideo()

AVIFile MOVFile void open(file){


OpenVideo(file);
}
+ open() + open()
+ close() + close() void close() {
+ play() + play() CloseFile();
}

void play() {
PlayFile();
}
Adapter

Allows to translate interfaces between two designs,


two libraries.
Can use double inheritance (if no name collision!), or
composition.
Note there is a small overhad may be noticeable if
the adapter is called millons of time...
Composite
Motivation: Treat in the same way objects and
composition of objects (should ring a bell!)
Example: pretty much the problem you have in
the assignment: the image to display is a
collection of basic shapes and complex
shapes, that are a combination of shapes
themselves...
Composite

Source: Design Patterns: Elements of Reusable Object Oriented Software.


Gamma, E., Helm, R., Johnson, R. and Vlissides, J. (so-called Gang of Four)
Composite example: assignment
design
AbstractShape
# position : int[2] 1..*
# color : char[3]
+ draw( display : BaseDisplay & )
+ clone() : AbstractShape *

CircleShape ComplexShape 1
- radius : int
+ draw( display : BaseDisplay & ) - shapes
+ clone() : AbstractShape * + draw( display : BaseDisplay & )
+ clone() : AbstractShape *
Composite
Defines class hierarchy that
contains simple and
composite objects.
Makes the client simple:
can handle all objects the
same way.
Can add new components
on the fly easily.
Decorator

Motivation: create add-ons that can be


applied on basic objects at run-time.
Example: consider how the rendering of the
text can be altered in a webpage. You can add
properties such as font, color, italic to alter a
paragraph's look.
Decorator

Source: Design Patterns: Elements of Reusable Object Oriented Software.


Gamma, E., Helm, R., Johnson, R. and Vlissides, J. (so-called Gang of Four)
Decorator example
AbstractText
1

+ display()

RawText TextFont TextColor


1 1
- text : string - font : FontType - color : ColorType

+ display() base + display() base


+ display()

AbstractText T = new TextColor( red, new TextFont( Arial, new RawText( Hello World ) ) );
T.display();

Hello world
Decorator
More flexible than static
inheritance: run-time!
Can add functionalities when
needed allow for simple
abstract classes.
Can be tricky to understand
and to maintain (document
your code!)
Summary
Design patterns form a useful toolbox.
Each pattern offer a solution for a design problem
can allow fast design of complex solutions.
Patterns should be adapted to the problem, and
simplified wherever possible:
a simpler design is generally a better design!
There are more, check the book!

You might also like