C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY...

59
C++ Design Patterns 1 C++ Design Patterns C++ Design Patterns DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013

Transcript of C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY...

Page 1: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 1

C++ Design PatternsC++ Design Patterns

DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY

Joey Paquet, Emil Vassev. 2007, 2011, 2013

Page 2: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 2

Outline

Introduction to Design PatternsIntroduction to Design Patterns Pattern’s ElementsPattern’s Elements Types of Design PatternsTypes of Design Patterns

C++ Design PatternsC++ Design Patterns Creational PatternsCreational Patterns Structural PatternsStructural Patterns Behavioral PatternsBehavioral Patterns

Page 3: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 3

Design Patterns

“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.” [1]

[Christopher Alexander – late 1970s] A Pattern Language A Timeless Way of Building

Design patterns capture the best practices of experienced object-oriented software developers.

Design patterns are solutions to general software development problems.

:: What is a Design Pattern?

Page 4: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 4

Design Patterns

In general, a pattern has four essential elements.

The pattern name The problem The solution The consequences

:: Pattern’s Elements – Pattern Name

Page 5: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 5

Design Patterns

The pattern name is a handle we can use to describe a design problem, its solutions, and consequences in a word or two.

Naming a pattern immediately increases the design vocabulary. It lets us design at a higher level of abstraction.

Having a vocabulary for patterns lets us talk about them. It makes it easier to think about designs and to communicate

them and their trade-offs to others.

:: Pattern’s Elements – The Pattern Name

Page 6: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 6

Design Patterns

The problem describes when to apply the pattern.

It explains the problem and its context. It might describe specific design problems such as how to

represent algorithms as objects. It might describe class or object structures that are

symptomatic of an inflexible design. Sometimes the problem will include a list of conditions that

must be met before it makes sense to apply the pattern.

:: Pattern’s Elements – The Problem

Page 7: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 7

Design Patterns

The solution describes the elements that make up the design, their relationships, responsibilities, and collaborations.

The solution doesn't describe a particular concrete design or implementation, because a pattern is like a template that can be applied in many different situations.

Instead, the pattern provides an abstract description of a design problem and how a general arrangement of elements (classes and objects in our case) solves it.

:: Pattern’s Elements – The Solution

Page 8: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 8

Design Patterns

The consequences are the results and trade-offs of applying the pattern.

The consequences for software often concern space and time trade-offs.

They may address language and implementation issues as well.

Since reuse is often a factor in object-oriented design, the consequences of a pattern include its impact on a system's flexibility, extensibility, or portability.

:: Pattern’s Elements – The Consequences

Page 9: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 9

Design Patterns

Erich Gamma, Richard Helm, Ralph Johnson and John Vlisides in their Design Patterns [gang of four] book define 23 design patterns divided into three types:

Creational patterns - create objects for you, rather than having you instantiate objects directly. This gives your program more flexibility in deciding which objects need to be created for a given case.

Structural patterns - help you compose groups of objects into larger structures, such as complex user interfaces or accounting data.

Behavioral patterns - help you define the communication between objects in your system and how the flow is controlled in a complex program.

:: Types

Page 10: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 10

C++ Design Patterns

The creational patterns deal with the best way to create instances of objects.

In C++, the simplest ways to create an instance of an object is by using the new operator or by simply declaring the variable in the local scope:

Fred* fred1 = new Fred(); //instance of Fred class

Fred fred2 ; //instance of Fred class

The amount of hard coding depends on how you create the object within your program.

In many cases, the exact nature of the object that is created could vary with the needs of the program and abstracting the creation process into a special “creator” class can make your program more flexible and general.

:: Creational Patterns and C++ I

Page 11: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 11

C++ Design Patterns

The Factory Pattern provides a simple decision making class that returns one of several possible subclasses of an abstract base class depending on the data that are provided.

The Abstract Factory Pattern provides an interface to create and return one of several families of related objects.

The Builder Pattern separates the construction of a complex object from its representation.

The Prototype Pattern starts with an initialized and instantiated class and copies or clones it to make new instances rather than creating new instances.

The Singleton Pattern is a class of which there can be no more than one instance. It provides a single global point of access to that instance.

:: Creational Patterns and C++ II

Page 12: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 12

The Factory Pattern

The Factory pattern returns an instance of one of several possible classes depending on the data provided to it.

:: How does it Work?

Here, x is a base class and classes xy and xz are derived from it. The Factory is a class that decides which of these subclasses to

return depending on the arguments you give it. The getClass() method passes in some value abc, and returns

some instance of the class x. Which one it returns doesn't matter to the programmer since they all have the same methods, but different implementations.

Page 13: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 13

The Factory Pattern:: The Shape Factory

class ShapeFactory { public: // Static method to create objects // Change is required only in this function static Shape* Create(string type){ if ( type == "circle" ) return new Circle(); if ( type == "square" ) return new Square(); return NULL;} private: //Constructor is made private to prevent instantiation ShapeFactory(){};};

Page 14: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 14

The Factory Pattern:: The Shape and Subclasses

//Superclass of all object that the Factory can createclass Shape { public: //common interface to all subtypes virtual void draw() = 0;};

class Circle : public Shape { public: void draw() { cout << "I am circle" << endl; }};

class Square : public Shape { public: void draw() { cout << "I am square" << endl; }};

Page 15: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 15

The Factory Pattern:: The Driver client

int main(){ // Give me a circle Shape* shape1 = ShapeFactory::Create("circle");

// Give me a square Shape* shape2 = ShapeFactory::Create("square"); shape1->draw(); // will call appropriate draw() shape2->draw(); // as it is defined as virtual delete shape1; delete shape2;}

Page 16: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 16

The Factory Pattern

You should consider using a Factory pattern when: A class can’t anticipate the kind of objects it must create. A class uses hierarchy of classes to specify which objects it creates. You want to localize the knowledge of which class gets created.

How to recognize the Factory pattern? The base class is abstract and the pattern must return a complete

working class. The base class contains default methods and is only subclassed for cases

where the default methods are insufficient. Parameters are passed to the factory telling it which of several class

types to return. In this case the classes may share the same method names but may do something quite different.

:: When to Use a Factory Pattern

Page 17: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 17

The Abstract Factory Pattern

The Abstract Factory pattern is one level of abstraction higher than the factory pattern.

This pattern returns one of several related classes, each of which can return several different objects on request. In other words, the Abstract Factory is a factory object that returns one of several factories.

One classic application of the abstract factory is the case where your system needs to support multiple “look-and-feel” user interfaces, such as Windows, Linux or Macintosh:

You tell the factory that you want your program to look like Windows and it returns a GUI factory which returns Windows-like objects.

When you request specific objects such as buttons, check boxes and windows, the GUI factory returns Windows instances of these visual interface components.

:: How does it Work?

Page 18: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 18

The Abstract Factory Pattern :: A Widget Factory

// Superclass of all objects to be created by all Factoriesclass Widget { public: //common interface to all created objects virtual void draw() = 0;};

//Supeclass of all Factories class WidgetFactory { public: //All specific kinds of objects that can be created virtual Widget* create_button() = 0; virtual Widget* create_menu() = 0;};

Page 19: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 19

The Abstract Factory Pattern :: The Motif Widget Factory

//Factory generating Motif Widgetsclass MotifWidgetFactory : public WidgetFactory { public: Widget* create_button() { return new MotifButton; } Widget* create_menu() { return new MotifMenu; }};

//Different specific kinds of Motif objectsclass MotifButton : public Widget { public: void draw() { cout << "MotifButton\n"; }};

class MotifMenu : public Widget { public: void draw() { cout << "MotifMenu\n"; }};

Page 20: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 20

The Abstract Factory Pattern :: The Windows Widget Factory

//Factory generating Windows Widgetsclass WindowsWidgetFactory : public WidgetFactory { public: Widget* create_button() { return new WindowsButton; } Widget* create_menu() { return new WindowsMenu; }};

//Different specific kinds of Windows objectsclass WindowsButton : public Widget { public: void draw() { cout << "WindowsButton\n"; }};

class WindowsMenu : public Widget { public: void draw() { cout << "WindowsMenu\n"; }};

Page 21: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 21

The Abstract Factory Pattern :: The Driver client

//uncomment the following to generate Motif widgets #define MOTIF//uncomment the following to generate Windows widgets //#define WINDOWS

int main(int argc, char *argv[]){ WidgetFactory *widget_factory; #ifdef MOTIF widget_factory = new MotifWidgetFactory;#else // WINDOWS widget_factory = new WindowsWidgetFactory;#endif

Widget* w[2] = {widget_factory->create_button(), widget_factory->create_menu()}; w[0]->draw(); //call appropriate draw() method w[1]->draw(); //of subclass of Widget object}

Page 22: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 22

The Abstract Factory Pattern

One of the main purposes of the Abstract Factory is that it isolates the concrete classes that are generated.

The actual class names of these classes are hidden in the factory and need not be known at the client level at all.

Because of the isolation of classes, you can change or interchange these product class families freely.

Since you generate only one kind of concrete class, this system keeps you for inadvertently using classes from different families of products.

While all of the classes that the Abstract Factory generates have the same base class, there is nothing to prevent some derived classes from having additional methods that differ from the methods of other classes.

:: Consequences of Abstract Factory

Page 23: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 23

The Builder Pattern

The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.

:: How does it Work? - I

Builder - specifies an abstract interface for creating parts of a Product object. ConcreteBuilder - constructs and assembles parts of the product by

implementing the Builder interface. Also, it defines and keeps track of the representation it creates and provides an interface for retrieving the product .

Director - constructs an object using the Builder interface. Product - represents the complex object under construction.

Page 24: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 24

The Builder Pattern

The client creates the Director object and configures it with the desired Builder object.

Director notifies the builder whenever a part of the product should be built. Builder handles requests from the director and adds parts to the product. The client retrieves the product from the builder.

The following interaction diagram illustrates how Builder and Director cooperate with a client.

:: How does it Work? - II

Page 25: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 25

The Builder Pattern

:: Example: Pizza Builder [5]

//Superclass of all kinds of objects to be created//Generically called “Product”class Pizza{ public: //Set all parts of the Product, and use the Product void setDough(const string& dough){ m_dough = dough;} void setSauce(const string& sauce){ m_sauce = sauce;} void setTopping(const string& topping){ m_topping = topping;} void open() const{ cout << "Pizza with " << m_dough << " dough, " << m_sauce << " sauce and " << m_topping << " topping. Mmm." << endl;} private: //Parts of the Product string m_dough; string m_sauce; string m_topping;};

Page 26: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 26

The Builder Pattern

:: Example: Pizza Builder [5]

class PizzaBuilder{ public: //get the built Pizza from the Builder Pizza* getPizza(){ return m_pizza; } //build a generic empty Pizza void createNewPizzaProduct(){ m_pizza = new Pizza; } //create each part of the Product according to subtypes virtual void buildDough() = 0; virtual void buildSauce() = 0; virtual void buildTopping() = 0; protected: //Product built by Pizza Builder Pizza* m_pizza;};

Page 27: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 27

The Builder Pattern

:: Example: Pizza Builder [5]

class HawaiianPizzaBuilder : public PizzaBuilder //Concrete Builder 1{ public: virtual void buildDough() //Build different parts of the pizza {m_pizza->setDough("cross");} //The construction process could be virtual void buildSauce() //more complex in a real-life example {m_pizza->setSauce("mild");} //The construction of the pizza part virtual void buildTopping() //depends on the type of pizza. {m_pizza->setTopping("ham+pineapple");}}; class SpicyPizzaBuilder : public PizzaBuilder //Concrete Builder 2{ public: virtual void buildDough() //The construction process may vary {m_pizza->setDough("pan baked");} //across different Concrete Builders. virtual void buildSauce() {m_pizza->setSauce("hot");} virtual void buildTopping() {m_pizza->setTopping("pepperoni+salami");}};

//There could be other Concrete Builders added for other kinds of pizza the Chef //designs later

Page 28: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 28

The Builder Pattern

:: Example: Pizza Builder [5]

class Cook //Director{ public: void setPizzaBuilder(PizzaBuilder* pb) //Use a concrete builder { //for building a specific m_pizzaBuilder = pb; //kind of Pizza. } Pizza* getPizza() //get the constructed Pizza { return m_pizzaBuilder->getPizza(); } void constructPizza() //Creational process to create { //a pizza using the builder. m_pizzaBuilder->createNewPizzaProduct(); m_pizzaBuilder->buildDough(); m_pizzaBuilder->buildSauce(); m_pizzaBuilder->buildTopping(); } private: PizzaBuilder* m_pizzaBuilder;};

Page 29: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 29

The Builder Pattern

:: Example: Pizza Builder [5]

//Pizza Builder Clientint main() { Cook cook; //Create the Director PizzaBuilder* hawaiianPizzaBuilder = //Create the Concrete Builder

new HawaiianPizzaBuilder; PizzaBuilder* spicyPizzaBuilder =

new SpicyPizzaBuilder; cook.setPizzaBuilder(hawaiianPizzaBuilder); //Tell the Director which Builder to use cook.constructPizza(); //Tell the Director to construct the Product Pizza* hawaiian = cook.getPizza(); //Client gets the Product hawaiian->open(); //Client uses the Product cook.setPizzaBuilder(spicyPizzaBuilder); //same for another kind of product cook.constructPizza(); Pizza* spicy = cook.getPizza(); spicy->open(); delete hawaiianPizzaBuilder; delete spicyPizzaBuilder; delete hawaiian; delete spicy;}

Page 30: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 30

The Builder Pattern

Use the Builder pattern when:

The algorithm for creating a complex object should be independent of the parts that make up the object and how they are assembled.

The construction process must allow different representations for the object that is constructed.

:: Applicability of Builder Pattern

Page 31: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 31

The Builder Pattern

A Builder lets you vary the internal representation of the product it builds. It also hides the details of how the product is assembled.

Each specific builder is independent of the others and of the rest of the program. This improves modularity and makes the addition of other builders relatively simple.

Because each builder constructs the final product step-by-step, depending on the data, you have more control over each final product that a Builder constructs.

A Builder pattern is somewhat like an Abstract Factory pattern in that both return classes made up of a number of methods and objects. The main difference is that while the Abstract Factory returns a family of related classes, the Builder constructs a complex object step by step depending on the data presented to it.

:: Consequences of Builder Pattern

Page 32: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 32

The Singleton Pattern

Sometimes it is appropriate to have exactly one instance of a class: window managers, print spoolers, filesystems.

Typically, those types of objects known as singletons, are accessed by disparate objects throughout a software system, and therefore require a global point of access.

The Singleton pattern addresses all the concerns above. With the Singleton design pattern you can:

Ensure that only one instance of a class is created. Provide a global point of access to the object. Allow multiple instances in the future without affecting a singleton

class' clients.

:: Definition & Applicability - I

Page 33: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 33

The Singleton Pattern

The Singleton pattern ensures a class has only one instance, and provides a global point of access to it.

The class itself is responsible for keeping track of its sole instance. The class can ensure that no other instance can be created (by intercepting requests to create new objects), and it can provide a way to access the instance.

Singletons maintain a static reference to the sole singleton instance and return a reference to that instance from a static instance() method.

:: Definition & Applicability - II

Page 34: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 34

The Singleton Pattern

The Singleton class maintains a static reference to the sinle singleton instance (s_instance) and returns that reference from the static Instance() method.

:: The Classic Singleton - I

class SingletonClass{ private: int m_value;

//static instance, allows static instance() method to access the instance static SingletonClass *s_instance; //private constructor prevents external instantiation SingletonClass(){ m_value = 0; }

public:

int get_value(){ return m_value; }

void increment_value(){ m_value++; }

//static method to create/access the singleton instance static SingletonClass *Instance() { if (!s_instance) s_instance = new SingletonClass(); return s_instance; }};

Page 35: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 35C++ Design Patterns 35

The Singleton Pattern

:: The Classic Singleton - II

// Allocating and initializing SingletonClass's// static data member. The pointer is being// allocated - not the object itself.SingletonClass *SingletonClass::s_instance = 0;

//two free functions manipulating the instancevoid foo(void){ SingletonClass::instance()->increment_value(); cout << "foo: global_ptr is " << SingletonClass::instance()->get_value() << '\n';}

void bar(void){ SingletonClass::instance()->increment_value(); cout << "bar: global_ptr is " << SingletonClass::instance()->get_value() << '\n';}

int main(int argc, char *argv[]){ cout << "main: global_ptr is " << SingletonClass::instance()->get_value() << '\n'; foo(); bar();}

Page 36: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 36

The Singleton Pattern

The Singleton class employs a technique known as lazy instantiation to create the singleton; as a result, the singleton instance is not created until the Instance() method is called for the first time. This technique ensures that singleton instances are created only when needed.

The Singleton class implements a protected constructor so clients cannot instantiate Singleton instances.

Protected constructors can be called by subclasses.

Solutions:Solutions:

We can make the Singleton constructor private so that only Singleton’s methods call it;

:: The Classic Singleton - III

Page 37: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 37

The Singleton Pattern

It can be difficult to subclass a Singleton, since this can only work if the base Singleton class has not yet been instantiated.

We can easily change a Singleton to allow a small number of instances where this is allowable and meaningful.

We can use the same approach to control the number of instances that the application uses. Only the operation that grants access to the Singleton instance needs to change.

The Singleton pattern permits refinement of operations and representation. The Singleton class may be subclassed, and it is easy to configure an application with an instance of this extended class. You can configure the application with an instance of the class you need at run-time.

:: Consequences of the Singleton Pattern

Page 38: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 38

Design Patterns

Structural patterns describe how classes and objects can be combined to form larger structures.

The difference between class patterns and object patterns is that class patterns describe how inheritance can be used to provide more useful program interfaces.

Object patterns, on the other hand, describe how objects can be composed into larger structures using object composition, or the inclusion of objects within other objects.

Some of the Structural patterns are: Adapter Composite Proxy Flyweight Façade Bridge Decorator

:: Structural Patterns

Page 39: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 39

Design Patterns

The Adapter pattern can be used to make one class interface match another to make programming easier.

The Composite pattern is a composition of objects, each of which may be either simple or itself a composite object.

The Proxy pattern is frequently a simple object that takes the place of a more complex object that may be invoked later, for example when the program runs in a network environment.

:: Structural Patterns - II

Page 40: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 40

Design Patterns

The Flyweight pattern is a pattern for sharing objects, where each instance does not contain its own state, but stores it externally. This allows efficient sharing of objects to save space, when there are many instances, but only a few different types.

The Façade pattern is used to make a single class represent an entire subsystem.

The Bridge pattern separates an object’s interface from its implementation, so you can vary them separately.

The Decorator pattern can be used to add responsibilities to objects dynamically.

:: Structural Patterns III

Page 41: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 41C++ Design Patterns 41

The Adapter Pattern

MotivationLike any adapter in the real world it is used to be an interface, a bridge between two objects that have the same functionality, but that are to be used in a different manner, i.e. have a different specification to their interfaces. In real world we have adapters for power supplies, adapters for camera memory cards, and so on.

The same concept applies to software components. You may have some class expecting some type of object and you have an object offering the same features, but exposing a different interface. You don't want to change existing classes, so you want to create an adapter.

Intent Convert the interface of a class into another interface that clients expect. Adapter lets classes work together, that could not otherwise because of

incompatible interfaces.

:: Definition & Applicability - I

Page 42: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 42C++ Design Patterns 42C++ Design Patterns 42

The Adapter Pattern

The classes/objects participating in adapter pattern:

Target - defines the domain-specific interface that Client uses.Adapter - adapts the interface Adaptee to the Target interface.Adaptee - defines an existing interface that needs adapting.Client - collaborates with objects conforming to the Target interface.

:: Definition & Applicability - II

Page 43: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 43C++ Design Patterns 43C++ Design Patterns 43C++ Design Patterns 43

The Adapter Pattern

The adapter pattern is used:

When you have a class (Target) that invokes methods defined in an interface and you have a another class (Adapter) that doesn't implement the interface but implements the operations that should be invoked from the first class through the interface. You can change none of the existing code. The adapter will implement the interface and will be the bridge between the two classes.

When you write a class (Target) for a generic use relying on some general interfaces and you have some implemented classes, not implementing the interface, that needs to be invoked by the Target class.

:: Definition & Applicability - III

Page 44: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 44C++ Design Patterns 44C++ Design Patterns 44C++ Design Patterns 44C++ Design Patterns 44

The Adapter Pattern

/*** The SquarePeg class.* This is the Target class.*/public class SquarePeg { public void insert(String str) { cout << "SquarePeg insert(): " << str;}}

/*** The RoundPeg class.* This is the Adaptee class.*/public class RoundPeg { public void insertIntoHole(String msg) { cout << “RoundPeg insertIntoHole(): " << msg;}}

If a client only understands the SquarePeg interface for inserting pegs using the insert() method, how can it insert round pegs, which are pegs, but that are inserted differently, using the insertIntoHole() method?

:: Example - I

Page 45: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 45C++ Design Patterns 45C++ Design Patterns 45C++ Design Patterns 45C++ Design Patterns 45C++ Design Patterns 45

The Adapter Pattern

Solution:

Design a RoundToSquarePeg adapter that enables to insertIntoHole() a RoundPeg object connected to the adapter to be inserted as a SquarePeg, using insert().

/*** The RoundToSquarePegAdapter class.* This is the Adapter class.* It adapts a RoundPeg to a SquarePeg.* Its interface is that of a SquarePeg.*/public class RoundToSquarePegAdapter: public SquarePeg { private RoundPeg roundPeg; public RoundToSquarePegAdapter(RoundPeg peg) { //the roundPeg is plugged into the adapter this.roundPeg = peg;} public void insert(String str) { //the roundPeg can now be inserted in the same manner as a squarePeg! roundPeg.insertIntoHole(str);}}

:: Example - II

Page 46: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 46C++ Design Patterns 46C++ Design Patterns 46C++ Design Patterns 46C++ Design Patterns 46C++ Design Patterns 46C++ Design Patterns 46

The Adapter Pattern

// Test program for Pegs.main(int argc, char *argv[]){ // Create some pegs. RoundPeg roundPeg = new RoundPeg(); SquarePeg squarePeg = new SquarePeg();

// Do an insert using the square peg. squarePeg.insert("Inserting square peg...");

// Now we'd like to do an insert using the round peg. // But this client only understands the insert() // method of pegs, not a insertIntoHole() method. // The solution: create an adapter that adapts // a square peg to a round peg!

PegAdapter adapter = new PegAdapter(roundPeg); adapter.insert("Inserting round peg...");

SquarePeg *sq_pegs[2] = {new SquarePeg(), new RoundToSquarePegAdapter(*roundPeg)}; sq_pegs[0]->insertIntoSquareHole("Inserting square peg [0]...\n"); sq_pegs[1]->insertIntoSquareHole("Inserting square peg [1]...\n");}

:: Example - III

Page 47: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 47C++ Design Patterns 47C++ Design Patterns 47C++ Design Patterns 47C++ Design Patterns 47C++ Design Patterns 47C++ Design Patterns 47C++ Design Patterns 47

The Adapter Pattern

More: two-way adapter!Solution: multiple inheritance!

public class SquarePeg { public virtual void insertSquarePeg(String str) { cout << "SquarePeg insertSquarePeg(): " << str;}}

public class RoundPeg { public virtual void insertRoundPeg(String msg) { cout << “RoundPeg insertRoundPeg(): " << msg;}}

class TwoWayPegAdapter: public SquarePeg, RoundPeg { private: RoundPeg roundPeg; SquarePeg squarePeg; public: TwoWayPegAdapter(RoundPeg peg) { //a roundPeg is plugged into the adapter this.roundPeg = peg;} TwoWayPegAdapter(SquarePeg peg) { //a squarePeg is plugged into the adapter this.squarePeg = peg;} void virtual insertRoundPeg(String str) { squarePeg.insertSquarePeg(str); } void virtual insertSquarePeg(String str) { roundPeg.insertRoundPeg(str); } }

:: Definition & Applicability - VII

Page 48: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 48C++ Design Patterns 48C++ Design Patterns 48C++ Design Patterns 48C++ Design Patterns 48C++ Design Patterns 48C++ Design Patterns 48C++ Design Patterns 48C++ Design Patterns 48

The Adapter Pattern

int main(int argc, char *argv[]){ RoundPeg *roundPeg = new RoundPeg(); SquarePeg *squarePeg = new SquarePeg();

SquarePeg *squarePegArray[2] = {squarePeg, new TwoWayPegAdapter(roundPeg)}; squarePegArray[0]->insertSquarePeg("Inserting Square Peg in squarePegArray[0]...\n"); squarePegArray[1]->insertSquarePeg("Inserting Square Peg in squarePegArray[1]...\n"); RoundPeg *roundPegArray[2] = {roundPeg, new TwoWayPegAdapter(squarePeg)}; roundPegArray[0]->insertRoundPeg("Inserting Round Peg in roundPegArray[0]...\n"); roundPegArray[1]->insertRoundPeg("Inserting Round Peg in roundPegArray[1]...\n");};

:: Definition & Applicability - VIII

Page 49: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 49C++ Design Patterns 49

Design Patterns

Observer pattern Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Null Object Provide an object as a surrogate for the lack of an object of a given type. The Null Object Pattern provides intelligent do nothing behavior, hiding the details from its collaborators.

Memento Capture the internal state of an object without violating encapsulation and thus providing a mean for restoring the object into initial state when needed.

Observer Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

:: Behavioral Patterns

Page 50: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 50C++ Design Patterns 50C++ Design Patterns 50C++ Design Patterns 50C++ Design Patterns 50C++ Design Patterns 50C++ Design Patterns 50C++ Design Patterns 50C++ Design Patterns 50

The Observer Pattern

Motivation

The cases when certain objects need to be informed about the changes occured in other objects are frequent. To have a good design means to decouple as much as possible and to reduce the dependencies. The Observer Design Pattern can be used whenever a subject has to be observed by one or more observers.

Intent

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

This pattern is a cornerstone of the Model-View-Controller architectural design, where the Model implements the mechanics of the program, and the Views are implemented as Observers that are as much uncoupled as possible to the Model components.

:: Definition & Applicability - I

Page 51: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51C++ Design Patterns 51

The Observer Pattern:: Definition & Applicability - II

Page 52: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52C++ Design Patterns 52

The Observer Pattern

The participants classes in the Observer pattern are:

Observable - interface or abstract class defining the operations for attaching and de-attaching observers to the client. In the GOF book this class/interface is known as Subject.

ConcreteObservable - concrete Observable class. It maintain the state of the observed object and when a change in its state occurs it notifies the attached Observers.

Observer - interface or abstract class defining the operations to be used to notify the Observer object.

ConcreteObserverA, ConcreteObserverB - concrete Observer implementations.

:: Definition & Applicability - III

Page 53: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53C++ Design Patterns 53

The Observer Pattern

Behavior

The client class instantiates the ConcreteObservable object. Then it instantiate and attaches the concrete observers to it using the methods defined in the Observable interface. Each time the state of the subject it's changing it notifies all the attached Observers using the methods defined in the Observer interface. When a new Observer is added to the application, all we need to do is to instantiate it in the client class and to add attach it to the Observable object. The classes already created will remain unchanged.

:: Definition & Applicability - IV

Page 54: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54C++ Design Patterns 54

The Observer Pattern

// Subject class, also known as “Observable”// class Observable { public: virtual ~Observable() {}; virtual void attach(Observer *); virtual void detach(Observer *); virtual void notify(); protected: Observable() {}; private: list<Observer*> _observers;};

:: Example - I

Page 55: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55C++ Design Patterns 55

The Observer Pattern

// A Sub-class of Observable: a Clock Timer//class ClockTimer : public Observable { public:     ClockTimer();      int GetHour(){return hour};     int GetMinute(){return minute};     int GetSecond(){return second};     void tick(){     // update internal time-keeping state      // ... // The Observable object notifies all its registered observers      notify();}; private: int hour; int minute; int second; };

In green are the changes to be applied to the class to be made an observable class.

:: Example - II

Page 56: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56C++ Design Patterns 56

The Observer Pattern

//Observer Class//class Observer { public:     virtual ~Observer();     virtual void Update(Subject* theChangeSubject) = 0; protected:     Observer(); };

The Observer class is a virtual class

:: Example - III

Page 57: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57C++ Design Patterns 57

The Observer Pattern

// A specific Observer to observe ClockTimers: DigitalClock//class DigitalClock: public Observer { public:     DigitalClock(ClockTimer* s){ //Upon instantiation, attaches itself to a ClockTimer _observable = s; _observable->attach(this);}     ~DigitalClock(){ //Upon destruction, detaches itself from its ClockTimer     _observable->detach(this);};      void Update(Subject* theChangedSubject){ //if the notification concerns my own subject, redraw my clock’s reading     if(theChangedSubject == _observable)         draw();};

    void draw(){      int hour = _subject->GetHour();      int minute = _subject->GetMinute();      int second = _subject->GetSecond();      cout << hour << ':' << minute << ':' << second << endl;};

private:     ClockTimer *_observable; };

:: Example - IV

Page 58: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58C++ Design Patterns 58

The Observer Pattern

int main(void) {   //Create a ClockTimer to be observed ClockTimer *timer = new ClockTimer;

//Create a DigitalClock that is connected to the ClockTimer  DigitalClock *digitalClock = new DigitalClock(timer);      //Advancing the ClockTimer updates the DigitalClock //as Tick() calls Update() after it changed its state while(true){ timer->tick();}}

:: Example - V

Page 59: C++ Design Patterns 1 DEPARTMENT OF COMPUTER SCIENCE AND SOFTWARE ENGINEERING CONCORDIA UNIVERSITY Joey Paquet, Emil Vassev. 2007, 2011, 2013.

C++ Design Patterns 59

[1] Christopher Alexander, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King, and Shlomo Angel. A Pattern Language. Oxford University Press, New York, 1977.

[2] Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Design Patterns – Elements of Reusable Object-Oriented Software, Adisson-Wesley, 1995.

[3] James W. Cooper, The Design Patterns – Java Companion Elements of Reusable Object-Oriented Software, Adisson-Wesley, 1998.

[4] James O. Coplien, Advanced C++ Programming Styles and Idioms, Addison-Wesley, Reading, MA., 1992.

[5] www.oodesign.com. Object-oriented design patterns. 2009. [6] C++ Programming WikiBook

http://en.wikibooks.org/wiki/C++_Programming/Code/Design_Patterns/Creational_Patterns

Resources