Showing posts with label Lists. Show all posts
Showing posts with label Lists. Show all posts

Wednesday, 17 November 2010

C++ example of Observer Design Pattern

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

Observers register themselves with the Subject as they are created. Whenever the Subject changes, it broadcasts to all registered Observers that it has changed.


The Observer defines a one-to-many relationship so that when one object changes state, the others are notified and updated automatically. Some auctions demonstrate this pattern. Each bidder possesses a numbered paddle that is used to indicate a bid. The auctioneer starts the bidding, and “observes” when a paddle is raised to accept the bid. The acceptance of the bid changes the bid price which is broadcast to all of the bidders in the form of a new bid.

Observer is a very popular pattern and its frequency of use is very high.

The following is an example of Observer Design Pattern:




//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Observer is part of Behavioral Patterns
//Behavioral Patterns deal with dynamic interactions among societies of classes and objects
//An Observer is a way of notifying change to a number of classes.

//We will take an example of Stock Price where, Observers can register to be told about
//the stock price change of a company

#include<iostream>
#include<string>
#include<list>

using namespace
std;


//Forward Declaration
class Stock;

// The 'Observer' interface
class IInvestor
{

public
:
virtual
void Update(Stock* stock){};
};


// The 'Subject' abstract class
class Stock
{

public
:
Stock(string symbol, double price) : symbol_(symbol), price_(price) { }
void
Attach(IInvestor* investor)
{

investors_.push_back(investor);
}

void
Detach(IInvestor* investor)
{

investors_.remove(investor);
}

void
Notify()
{

list<IInvestor*>::iterator it = investors_.begin();
while
(it != investors_.end())
{
(*
it)->Update(this);
++
it;
}
}

double
GetPrice(void)
{

return
price_;
}

void
SetPrice(double price)
{

price_ = price;
Notify();
}

string GetSymbol(void)
{

return
symbol_;
}


private
:
string symbol_;
double
price_;
list<IInvestor*> investors_;

Stock();
};


// The 'ConcreteSubject' class
class Company : public Stock
{

public
:
Company(string name, string symbol, double price) : name_(name), Stock(symbol, price) {}
string GetName(void)
{

return
name_;
}

private
:
string name_;
};


// The 'ConcreteObserver' class
class Investor : public IInvestor
{

public
:
Investor(string name) : name_(name){}
void
Update(Stock* stock)
{

cout<<"Notified "<<name_<<" about "<<(reinterpret_cast<Company*>(stock))->GetName() \
<<
" change to "<<stock->GetSymbol()<<stock->GetPrice()<<endl;
}

private
:
string name_;
Investor();
};


//The Main method
int main()
{

Company* c1 = new Company("Google", "$", 123.0);
cout<<"Created company Google with Stock Price 123.0\n"<<endl;

Investor* i1 = new Investor("Billy");
c1->Attach(i1);
cout<<"Created investor Billy following Google\n"<<endl;

c1->SetPrice(125.0);

Investor* i2 = new Investor("Timmy");
c1->Attach(i2);
Investor* i3 = new Investor("Lenny");
c1->Attach(i3);
cout<<"\nCreated investor Timmy and Lenny following Google\n"<<endl;

c1->SetPrice(145.0);

c1->Detach(i1);
c1->Detach(i3);
cout<<"\nInvestor Billy and Lenny not interested in Google anymore\n"<<endl;

c1->SetPrice(165.0);

delete
i1;
delete
i2;
delete
i3;
delete
c1;

return
0;
}



The output is as follows:
Further Reading:




Wednesday, 11 August 2010

C++ example for Factory Method Design Pattern

The Factory Method Design Pattern defines an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. This design pattern is used very frequently in practice.

The following is an example of Factory Method Design Pattern:

//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Factory Method is part of Creational Patterns
//Creational Patterns deal with initializing and configuring classes and objects
//Factory Method creates an instance of several derived classes

//We will take an example of creating Pages for Document.
//There are 2 types of Document: Resume and Report
//Different Document can instantiate different Pages based on their requirements

#include <iostream>
#include <string>
#include <list>

using namespace
std;

//Create the abstract 'Product' class
class Page
{

public
:
virtual
string GetPageName(void) = 0;
};


//'ConcreteProduct'#1 class
class SkillsPage : public Page
{

public
:
string GetPageName(void)
{

return
"SkillsPage";
}
};


//'ConcreteProduct'#2 class
class EducationPage : public Page
{

public
:
string GetPageName(void)
{

return
"EducationPage";
}
};


//'ConcreteProduct'#3 class
class ExperiencePage : public Page
{

public
:
string GetPageName(void)
{

return
"ExperiencePage";
}
};


//'ConcreteProduct'#4 class
class IntroductionPage : public Page
{

public
:
string GetPageName(void)
{

return
"IntroductionPage";
}
};


//'ConcreteProduct'#5 class
class ResultsPage : public Page
{

public
:
string GetPageName(void)
{

return
"ResultsPage";
}
};


//'ConcreteProduct'#6 class
class ConclusionPage : public Page
{

public
:
string GetPageName(void)
{

return
"ConclusionPage";
}
};


//'ConcreteProduct'#7 class
class SummaryPage : public Page
{

public
:
string GetPageName(void)
{

return
"SummaryPage";
}
};


//'ConcreteProduct'#8 class
class BibliographyPage : public Page
{

public
:
string GetPageName(void)
{

return
"BibliographyPage";
}
};


//Create the abstract 'Creator' class
class Document
{

public
:
//constructor
Document()
{

//CreatePages(); - Cannot be called directly in constructor because its virtual
//Should be called in the Derived class
}
void
AddPages(Page* page)
{

pages_.push_back(page);
}

const
list<Page*>& GetPages(void)
{

return
pages_;
}

//Factory Method
virtual void CreatePages(void) = 0;
private
:
list<Page*> pages_;
};


//Create the 'ConcreteCreator' # 1 class
class Resume : public Document
{

public
:
Resume()
{

CreatePages();
}

void
CreatePages(void)
{

AddPages(new SkillsPage());
AddPages(new EducationPage());
AddPages(new ExperiencePage());
}
};


//Create the 'ConcreteCreator' # 2 class
class Report : public Document
{

public
:
Report()
{

CreatePages();
}

void
CreatePages(void)
{

AddPages(new SummaryPage());
AddPages(new IntroductionPage());
AddPages(new ResultsPage());
AddPages(new ConclusionPage());
AddPages(new BibliographyPage());
}
};



//The Main method
int main()
{

//Create two types of documents - constructors call Factory method
Document* doc1 = new Resume();
Document* doc2 = new Report();

//Get and print the pages of the first document
list<Page*>& doc1Pages = const_cast<list<Page*>&> (doc1->GetPages());
cout << "\nResume Pages -------------" << endl;
for
(list<Page*>::iterator it = doc1Pages.begin(); it != doc1Pages.end(); it++)
{

cout << "\t" << (*it)->GetPageName() << endl;
}


//Get and print the pages of the second document
list<Page*>& doc2Pages = const_cast<list<Page*>&> (doc2->GetPages());
cout << "\nReport Pages -------------" << endl;
for
(list<Page*>::iterator it = doc2Pages.begin(); it != doc2Pages.end(); it++)
{

cout << "\t" << (*it)->GetPageName() << endl;
}


return
0;
}


The output is as follows:

Wednesday, 24 February 2010

The power of 'typedef' in C++

C++ allows the definition of our own types based on other existing data types. We can do this using the keyword typedef, whose format is:

typedef existing_type new_type_name ;

where existing_type is a C++ fundamental or compound type and new_type_name is the name for the new type we are defining.

For example:
typedef char C;
typedef unsigned int WORD;
typedef char * pChar;
typedef char field [50];

There are many scenarios where using typedef's are very advantageous. The following program is written based on the reasons for using typedef's as defined by Herb Sutter in his book "More Exceptional C++"



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Program showing the advantages of using typedefs in C++

#include<iostream>
#include<map>
#include<vector>
#include<list>
#include<assert.h>

using namespace
std;

//Comment/Uncomment as required
//#define USING_MAPS
#define USING_OTHER_STL

//5 - Portability: Useful if different users want to use different STL classes
#if defined USING_MAPS
typedef map<int,int> table; //1 - Typeability: table is easier to type
#else
//4 - Flexibility: In future you could replace a map by a vector for example
typedef vector<int> table;
//typedef list<int> table;
#endif

typedef
table::iterator tableIter;

//map<int,int> multiplicationTableTill10(int num); - not very readable
table multiplicationTableTill10(int num); //2 - Readability: Easier to read

int
main()
{

int
i = 1;
table t = multiplicationTableTill10(7);
for
(tableIter t_iter = t.begin(); t_iter != t.end(); ++t_iter, ++i)
{

#if defined USING_MAPS
cout<<"7 * "<<i<<" = "<<t[i]<<endl;
#elif defined USING_OTHER_STL
cout<<"7 * "<<i<<" = "<<*t_iter<<endl;
#else
assert(0);
#endif
}
return
0;
}


typedef
int Multiplier; //int is also now written as Multiplier

//This program creates a multiplication table of the number input from 1 to 10
table multiplicationTableTill10(int num)
{

table t;
tableIter t_iter;
//3 - Communication: Multiplier is more meaningful then int in the case below
for(Multiplier i = 1; i <= 10; i++)
{

#if defined USING_MAPS
t[i] = num * i;
#elif defined USING_OTHER_STL
t_iter = t.end();
t.insert(t_iter, num * i);
#else
assert(0);
#endif
}
return
t;
}






The Output is as follows:



More information on Typedefs: