Page 1 of 1

The Command Pattern (C++) Choosing an operation at runtime with this popular G.o.F. Design Patte Rate Topic: ***** 1 Votes

#1 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 856
  • View blog
  • Posts: 2,339
  • Joined: 20-August 07

Posted 29 November 2007 - 01:39 PM

Design Patterns in C++ - The Command Pattern

Preface
This article is aimed at readers at a more advanced level of understanding of the C++ language, and assumes familiarity with C++'s object oriented capabilities, as well as some understanding of the Standard Template Library. This article is intended for anybody who wishes to explore new techniques of object oriented software design and problem solving. The example shown takes a fairly common programming problem and completely re-factors the 'traditional' structured procedural solution into an object-oriented solution.


Introduction
Design Patterns are a language-independent idea, which harness the power of object-oriented programming languages, allowing commonly recurring problems to be tackled in some surprising and elegant ways. Ideally, this article probably belongs in a language-neutral zone dedicated to computer science theory, but the implementation of design patterns can vary as much as the languages in which they are used.

This article focuses on C++, and specifically, the Command Pattern, as pioneered by the "Gang Of Four" (GoF) in their book "Design Patterns: Elements of re-usable Object Oriented Software".
http://www.amazon.co...l/dp/0201633612

The Command Pattern is a particularly flexible and powerful design pattern, able to streamline decision making and selection by doing something that most object-oriented languages don't naturally do - treating operations or commands as objects in their own right, allowing related commands to be grouped together and picked out at runtime, without a tedious If/then/else structure.


A common problem
This one should be familiar to all computer science students - create a program which sends the user a list of options, such as a vending machine, a calculator, a radio station selector, etc. and performs a different task dependent on the user's choice. The command pattern is not concerned with the "ask a user" part, but what happens once the user has made his/her selection.

Consider a program which displays a number in either Hexadecimal, Octal or Binary representation, based on the user's choice. The obvious solution may be to write several functions which perform the conversion, and a switch-based menu to make a decision of which function to call.
	string output;
	switch( toupper(x) )
	{
	case 'O':   output = to_oct(num);
				break;
	case 'H':   output = to_hex(num);
				break;
	case 'B':   output = to_bin(num);
				break;
	default:	output = "invalid";
	} 

The code works, but its design is rather rigid. Every time the operations change, the switch block needs to be modified. At the moment, operations are just functions which exist completely independently of each another, even though they're all in fact fairly similar, and selection is solely based on different character values. (These character values acting like runtime identifiers for the operations)
A better solution would build in some kind of relationship between all the operations, and tag each one with their character value identifier.


The conversion operations
Unfortunately, functions in C++ are like second-class citizens - You can only do two things with them, call them, or take their address. Taking the address of a function and storing it for later use may be of limited worth, but hardly elegant, and doesn't really build a very tight relationship between the operations.

The better alternative is to create a Functor or Function Object - that is, an object which behaves like a function. A function object is an instance of a class which has a Do Something method. That method can be anything, but for each distinct operation, a seperate class is needed.

Here's a rundown of the three operations as they stand, completely unrelated to each another as far as C++ is concerned.
std::string to_hex(int i)
{
	std::stringstream ss;
	ss << std::hex << i;
	return ss.str();
}

std::string to_oct(int i)
{
	std::stringstream ss;
	ss << std::oct << i;
	return ss.str();
}

std::string to_bin(int i)
{
	std::bitset< sizeof(i) * CHAR_BIT > bits(i);
	std::stringstream ss;
	ss << bits;
	return ss.str();
}




Function relationships
In order to build a relationship between anything in C++, some common ground is needed. Looking closely at the way these functions are called, It should be pretty clear that all the operations have several features in common; They all take a single int parameter, and they all return a string.
- In fact, aside from the function names, the signatures are identical. This is ideal, because now the functions can all be rewritten within functor classes, and related using a general-case class that exhibits all these common features. (The general-case class will be called converter in this example).

class converter
{
public:
	virtual std::string convert(int) = 0;
}; 


The convert signature is the all-purpose signature which generalises all the operations in the program; For this reason it is declared a pure virtual function. That is, a function which on its own, cannot do anything meaningful, and will rely on derived classes to provide a valid implementation.
- All derived classes must override the convert method - Think of this as a sort of 'contractual obligation' on the part of any class which derives from converter. The compiler will fire out an error towards any class that does not meet this obligation

- This being the case, it is given that converter must be an abstract base class; a class which cannot meaningfully represent objects on its own.



Specialisation
All functors must have a "do something" method - in this case, that method is called convert. It exhibits the common features of the conversion functions; a return type of string and a single int parameter. This is the framework upon which the operations will be written, as specialised derived classes of converter, which all have specialised implementations of the convert method depending on their behaviour.

Specialisation has another name in Object-oriented design - inheritance. The specialised functor classes will all 'inherit' from the abstract base class converter, thus the relationship between the operations is established through the base class.
class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
}; 



Fitting the pieces together
The command pattern structure is complete, but its still not clear how this helps streamline the selection process; the operations still need to be tied to their identifiers. A kind of dictionary is needed, whereby some user-supplied value can be automatically resolved to its corresponding operation without the use of a switch or an if/else block

The C++ Standard Template Library provides an ideal facility, designed for such situations where 'dictionaries' are needed - the <map> library is capable of mapping almost any value to any other value or object of a different type with ease. The STL map is known as an associative container because of its ability to associate values to objects of a certain type.

In this case, the lookup value or key value will be a char, but the individual operations are now tucked away in their own classes, each of a distinct, different type. It would be no good to pick one of these types as the associated type, since whichever one is used, the others would not be able to fit.
- The only choice left is the abstract base class, however, the base class cannot be instantiated, nor can the base class hold any of the operations themselves. This means that the map will not be able to physically hold the functors, but must instead hold pointers - the functors themselves will need to be created seperately.
	std::map<char, converter*> dict;
	dict.insert( std::make_pair( 'B', new bin_converter ) );
	dict.insert( std::make_pair( 'O', new oct_converter ) );
	dict.insert( std::make_pair( 'H', new hex_converter ) );



Now the character identifiers and their operations are neatly tied together in a dictionary object. Instead of the switch block from the original program, the selection process now looks like this
	std::map<char, converter*>::const_iterator iter;
	iter = dict.find( toupper(x) );
	if( iter != dict.end() )
		output = iter->second->convert( num );
	else
		output = "Invalid";




Wrapping it up
Perfect? Not quite. Everything is peachy from a functionality point of view; dynamic binding is more than capable of handling the selection process, and the dictionary is completely extensible. However, the dictionary is using dynamically allocated memory, which means the programmer must be careful not to "leak" the functors. Memory leaks are a big 'no-no' in software development, so its appropriate that the command pattern uses a technique to ensure that the dictionary is capable of cleaning up after itself, without the programmer needing to do anything else.

Handling dynamically allocated memory is such a commonly recurring issue, that the next version of the C++ standard will include a feature known as 'Automatic garbage collection' to handle it. For now though, there are idioms available which help programmers prevent memory leaks. The idiom needed here is known as RAII (Resource Acquisition Is Initialisation), though its name is unimportant, the technique is simple and efficient at cleaning up unused memory from the heap.

To facilitate the RAII idiom, the dictionary will be wrapped up inside its own class, which will have a destructor defined. The destructor can delete all of its allocated functors when a dictionary object is destroyed.
- Since the dictionary map is going to be locked up inside a class, it would also make sense to provide a lookup method for the user to interact with the dictionary. (The lookup method will follow on the same logic as the selection process shown above)
class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		// Populate the dictionary with converter operations.
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};



For anyone reading this code who has spotted that converter does not possess a virtual destructor, the class is actually well-formed, since none of the derived classes have destructors either. But since convert is already a virtual method, then for the sake of extensibility and safety, it would be a good idea to add an empty virtual destructor to the converter class, so not to fall foul of one of C++'s more subtle "gotcha's".


Finally
The complete, working version of the integer base conversion program using the command pattern, including an example in main() of how the example 'command dictionary' may be used to convert a number's representation.

#include <iostream>
#include <string>
#include <bitset>
#include <sstream>
#include <map>
#include <cctype>

class converter
{
public:
	virtual std::string convert(int) = 0;
	virtual ~converter() {}
};

class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
};

class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};

int main()
{
	using namespace std;

	int num = 1234; 
	char ch = 'h';
	string output = "";
	dictionary dict;

	converter* con = dict.lookup( ch );

	if( con != NULL )
		output = con->convert( num );
	else
		output = "Invalid";

	cout << "Result: " << output;
} 



Summary
The command pattern is a powerful and flexible design idiom, commonly used in Graphical User Interface design to handle events and commands issued by a user. Design patterns are intended to allow greater modularity when designing programs, reducing the dependencies placed on any given block of code.

Among other things, this article should demonstrate that object oriented design is not about reducing the number of lines of code in a program, but about allowing problems to be broken down into sub-problems, producing small, reusable modules at every step along the way. Ultimately this approach should pave the way for larger problems to be tackled more easily.



References
Design Patterns: Elements of re-usable Object Oriented Software - Gamma et al.
The C++ Programming Language Special Ed. - Bjarne Stroustrup
Thinking in C++ Vol. 2 - Bruce Eckel



Practise Exercises
Think you understand the command pattern? Challenge yourself!

(1) Using the command pattern framework above to add an operation that outputs a string with the number's digits in reverse order.

(2) Create a command pattern framework which simulates a simple calculator, with operations such as add, subtract and multiply.

Is This A Good Question/Topic? 3
  • +

Replies To: The Command Pattern (C++)

#2 skyhawk133  Icon User is offline

  • Head DIC Head
  • member icon

Reputation: 1875
  • View blog
  • Posts: 20,284
  • Joined: 17-March 01

Posted 29 November 2007 - 04:00 PM

Awesome tutorial. Let's get this bad boy approved!
Was This Post Helpful? 0
  • +
  • -

#3 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 856
  • View blog
  • Posts: 2,339
  • Joined: 20-August 07

Posted 29 November 2007 - 05:50 PM

View Postskyhawk133, on 29 Nov, 2007 - 11:00 PM, said:

Awesome tutorial. Let's get this bad boy approved!

Thanks for the positive comment! Sorry its been a while since the last submission! Credit due to NickDMax for making the suggestion about design patterns in the first place :D
Was This Post Helpful? 0
  • +
  • -

#4 jjhaag  Icon User is offline

  • me editor am smartastic
  • member icon

Reputation: 44
  • View blog
  • Posts: 1,789
  • Joined: 18-September 07

Posted 30 November 2007 - 04:39 AM

Not much to do here except echo skyhawk's first comment. This tutorial is exceptionally well-written, and is a great demonstration of a number of pretty advanced techniques. Keep up the good work :^:
Was This Post Helpful? 0
  • +
  • -

#5 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2250
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Posted 01 December 2007 - 08:12 PM

I love that you threw function objects in there! That was another area that I thought could use a tutorial -- nice to see it here. :^:
Was This Post Helpful? 0
  • +
  • -

#6 Forumuser  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 08-April 08

Posted 08 April 2008 - 10:34 PM

I think this example suits as an example of strategy pattern.
In the given code, the object is not encapuslated into a command. I have modified the code as below. Please suggest if following code suits as a command pattern.

class command
{
public:
	virtual std::string execute(int num)=0;
};

class convertercommand:public command
{
private:
	converter* c;
public:
	   
	  convertercommand(converter* c1)
	  {
	   c=c1;
	  }
	  std::string execute(int num)
	  {
		 return c->convert(num);
	  }
	  
};
int main()
{
	using namespace std;

	int num = 1234; 
	char ch = 'h';
	string output = "";
	dictionary dict;

	converter* con= dict.lookup( ch );
	convertercommand* c1=new convertercommand(con);
	if( c1 != NULL )
		output = c1->execute( num );
	else
		output = "Invalid";

	cout << "Result: " << output;
	delete c1;
}


Was This Post Helpful? 0
  • +
  • -

#7 Forumuser  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 08-April 08

Posted 14 April 2008 - 11:51 PM

View PostForumuser, on 8 Apr, 2008 - 10:34 PM, said:

Please reply.

Was This Post Helpful? 0
  • +
  • -

#8 sssunny  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 31-July 09

Posted 31 July 2009 - 03:13 AM

View PostBench, on 29 Nov, 2007 - 12:39 PM, said:

Design Patterns in C++ - The Command Pattern

Preface
This article is aimed at readers at a more advanced level of understanding of the C++ language, and assumes familiarity with C++'s object oriented capabilities, as well as some understanding of the Standard Template Library. This article is intended for anybody who wishes to explore new techniques of object oriented software design and problem solving. The example shown takes a fairly common programming problem and completely re-factors the 'traditional' structured procedural solution into an object-oriented solution.


Introduction
Design Patterns are a language-independent idea, which harness the power of object-oriented programming languages, allowing commonly recurring problems to be tackled in some surprising and elegant ways. Ideally, this article probably belongs in a language-neutral zone dedicated to computer science theory, but the implementation of design patterns can vary as much as the languages in which they are used.

This article focuses on C++, and specifically, the Command Pattern, as pioneered by the "Gang Of Four" (GoF) in their book "Design Patterns: Elements of re-usable Object Oriented Software".
http://www.amazon.co...l/dp/0201633612

The Command Pattern is a particularly flexible and powerful design pattern, able to streamline decision making and selection by doing something that most object-oriented languages don't naturally do - treating operations or commands as objects in their own right, allowing related commands to be grouped together and picked out at runtime, without a tedious If/then/else structure.


A common problem
This one should be familiar to all computer science students - create a program which sends the user a list of options, such as a vending machine, a calculator, a radio station selector, etc. and performs a different task dependent on the user's choice. The command pattern is not concerned with the "ask a user" part, but what happens once the user has made his/her selection.

Consider a program which displays a number in either Hexadecimal, Octal or Binary representation, based on the user's choice. The obvious solution may be to write several functions which perform the conversion, and a switch-based menu to make a decision of which function to call.
	string output;
	switch( toupper(x) )
	{
	case 'O':   output = to_oct(num);
				break;
	case 'H':   output = to_hex(num);
				break;
	case 'B':   output = to_bin(num);
				break;
	default:	output = "invalid";
	} 

The code works, but its design is rather rigid. Every time the operations change, the switch block needs to be modified. At the moment, operations are just functions which exist completely independently of each another, even though they're all in fact fairly similar, and selection is solely based on different character values. (These character values acting like runtime identifiers for the operations)
A better solution would build in some kind of relationship between all the operations, and tag each one with their character value identifier.


The conversion operations
Unfortunately, functions in C++ are like second-class citizens - You can only do two things with them, call them, or take their address. Taking the address of a function and storing it for later use may be of limited worth, but hardly elegant, and doesn't really build a very tight relationship between the operations.

The better alternative is to create a Functor or Function Object - that is, an object which behaves like a function. A function object is an instance of a class which has a Do Something method. That method can be anything, but for each distinct operation, a seperate class is needed.

Here's a rundown of the three operations as they stand, completely unrelated to each another as far as C++ is concerned.
std::string to_hex(int i)
{
	std::stringstream ss;
	ss << std::hex << i;
	return ss.str();
}

std::string to_oct(int i)
{
	std::stringstream ss;
	ss << std::oct << i;
	return ss.str();
}

std::string to_bin(int i)
{
	std::bitset< sizeof(i) * CHAR_BIT > bits(i);
	std::stringstream ss;
	ss << bits;
	return ss.str();
}




Function relationships
In order to build a relationship between anything in C++, some common ground is needed. Looking closely at the way these functions are called, It should be pretty clear that all the operations have several features in common; They all take a single int parameter, and they all return a string.
- In fact, aside from the function names, the signatures are identical. This is ideal, because now the functions can all be rewritten within functor classes, and related using a general-case class that exhibits all these common features. (The general-case class will be called converter in this example).

class converter
{
public:
	virtual std::string convert(int) = 0;
}; 


The convert signature is the all-purpose signature which generalises all the operations in the program; For this reason it is declared a pure virtual function. That is, a function which on its own, cannot do anything meaningful, and will rely on derived classes to provide a valid implementation.
- All derived classes must override the convert method - Think of this as a sort of 'contractual obligation' on the part of any class which derives from converter. The compiler will fire out an error towards any class that does not meet this obligation

- This being the case, it is given that converter must be an abstract base class; a class which cannot meaningfully represent objects on its own.



Specialisation
All functors must have a "do something" method - in this case, that method is called convert. It exhibits the common features of the conversion functions; a return type of string and a single int parameter. This is the framework upon which the operations will be written, as specialised derived classes of converter, which all have specialised implementations of the convert method depending on their behaviour.

Specialisation has another name in Object-oriented design - inheritance. The specialised functor classes will all 'inherit' from the abstract base class converter, thus the relationship between the operations is established through the base class.
class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
}; 



Fitting the pieces together
The command pattern structure is complete, but its still not clear how this helps streamline the selection process; the operations still need to be tied to their identifiers. A kind of dictionary is needed, whereby some user-supplied value can be automatically resolved to its corresponding operation without the use of a switch or an if/else block

The C++ Standard Template Library provides an ideal facility, designed for such situations where 'dictionaries' are needed - the <map> library is capable of mapping almost any value to any other value or object of a different type with ease. The STL map is known as an associative container because of its ability to associate values to objects of a certain type.

In this case, the lookup value or key value will be a char, but the individual operations are now tucked away in their own classes, each of a distinct, different type. It would be no good to pick one of these types as the associated type, since whichever one is used, the others would not be able to fit.
- The only choice left is the abstract base class, however, the base class cannot be instantiated, nor can the base class hold any of the operations themselves. This means that the map will not be able to physically hold the functors, but must instead hold pointers - the functors themselves will need to be created seperately.
	std::map<char, converter*> dict;
	dict.insert( std::make_pair( 'B', new bin_converter ) );
	dict.insert( std::make_pair( 'O', new oct_converter ) );
	dict.insert( std::make_pair( 'H', new hex_converter ) );



Now the character identifiers and their operations are neatly tied together in a dictionary object. Instead of the switch block from the original program, the selection process now looks like this
	std::map<char, converter*>::const_iterator iter;
	iter = dict.find( toupper(x) );
	if( iter != dict.end() )
		output = iter->second->convert( num );
	else
		output = "Invalid";




Wrapping it up
Perfect? Not quite. Everything is peachy from a functionality point of view; dynamic binding is more than capable of handling the selection process, and the dictionary is completely extensible. However, the dictionary is using dynamically allocated memory, which means the programmer must be careful not to "leak" the functors. Memory leaks are a big 'no-no' in software development, so its appropriate that the command pattern uses a technique to ensure that the dictionary is capable of cleaning up after itself, without the programmer needing to do anything else.

Handling dynamically allocated memory is such a commonly recurring issue, that the next version of the C++ standard will include a feature known as 'Automatic garbage collection' to handle it. For now though, there are idioms available which help programmers prevent memory leaks. The idiom needed here is known as RAII (Resource Acquisition Is Initialisation), though its name is unimportant, the technique is simple and efficient at cleaning up unused memory from the heap.

To facilitate the RAII idiom, the dictionary will be wrapped up inside its own class, which will have a destructor defined. The destructor can delete all of its allocated functors when a dictionary object is destroyed.
- Since the dictionary map is going to be locked up inside a class, it would also make sense to provide a lookup method for the user to interact with the dictionary. (The lookup method will follow on the same logic as the selection process shown above)
class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		// Populate the dictionary with converter operations.
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};



For anyone reading this code who has spotted that converter does not possess a virtual destructor, the class is actually well-formed, since none of the derived classes have destructors either. But since convert is already a virtual method, then for the sake of extensibility and safety, it would be a good idea to add an empty virtual destructor to the converter class, so not to fall foul of one of C++'s more subtle "gotcha's".


Finally
The complete, working version of the integer base conversion program using the command pattern, including an example in main() of how the example 'command dictionary' may be used to convert a number's representation.

#include <iostream>
#include <string>
#include <bitset>
#include <sstream>
#include <map>
#include <cctype>

class converter
{
public:
	virtual std::string convert(int) = 0;
	virtual ~converter() {}
};

class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
};

class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};

int main()
{
	using namespace std;

	int num = 1234; 
	char ch = 'h';
	string output = "";
	dictionary dict;

	converter* con = dict.lookup( ch );

	if( con != NULL )
		output = con->convert( num );
	else
		output = "Invalid";

	cout << "Result: " << output;
} 



Summary
The command pattern is a powerful and flexible design idiom, commonly used in Graphical User Interface design to handle events and commands issued by a user. Design patterns are intended to allow greater modularity when designing programs, reducing the dependencies placed on any given block of code.

Among other things, this article should demonstrate that object oriented design is not about reducing the number of lines of code in a program, but about allowing problems to be broken down into sub-problems, producing small, reusable modules at every step along the way. Ultimately this approach should pave the way for larger problems to be tackled more easily.



References
Design Patterns: Elements of re-usable Object Oriented Software - Gamma et al.
The C++ Programming Language Special Ed. - Bjarne Stroustrup
Thinking in C++ Vol. 2 - Bruce Eckel



Practise Exercises
Think you understand the command pattern? Challenge yourself!

(1) Using the command pattern framework above to add an operation that outputs a string with the number's digits in reverse order.

(2) Create a command pattern framework which simulates a simple calculator, with operations such as add, subtract and multiply.



View PostBench, on 29 Nov, 2007 - 12:39 PM, said:

Design Patterns in C++ - The Command Pattern

Preface
This article is aimed at readers at a more advanced level of understanding of the C++ language, and assumes familiarity with C++'s object oriented capabilities, as well as some understanding of the Standard Template Library. This article is intended for anybody who wishes to explore new techniques of object oriented software design and problem solving. The example shown takes a fairly common programming problem and completely re-factors the 'traditional' structured procedural solution into an object-oriented solution.


Introduction
Design Patterns are a language-independent idea, which harness the power of object-oriented programming languages, allowing commonly recurring problems to be tackled in some surprising and elegant ways. Ideally, this article probably belongs in a language-neutral zone dedicated to computer science theory, but the implementation of design patterns can vary as much as the languages in which they are used.

This article focuses on C++, and specifically, the Command Pattern, as pioneered by the "Gang Of Four" (GoF) in their book "Design Patterns: Elements of re-usable Object Oriented Software".
http://www.amazon.co...l/dp/0201633612

The Command Pattern is a particularly flexible and powerful design pattern, able to streamline decision making and selection by doing something that most object-oriented languages don't naturally do - treating operations or commands as objects in their own right, allowing related commands to be grouped together and picked out at runtime, without a tedious If/then/else structure.


A common problem
This one should be familiar to all computer science students - create a program which sends the user a list of options, such as a vending machine, a calculator, a radio station selector, etc. and performs a different task dependent on the user's choice. The command pattern is not concerned with the "ask a user" part, but what happens once the user has made his/her selection.

Consider a program which displays a number in either Hexadecimal, Octal or Binary representation, based on the user's choice. The obvious solution may be to write several functions which perform the conversion, and a switch-based menu to make a decision of which function to call.
	string output;
	switch( toupper(x) )
	{
	case 'O':   output = to_oct(num);
				break;
	case 'H':   output = to_hex(num);
				break;
	case 'B':   output = to_bin(num);
				break;
	default:	output = "invalid";
	} 

The code works, but its design is rather rigid. Every time the operations change, the switch block needs to be modified. At the moment, operations are just functions which exist completely independently of each another, even though they're all in fact fairly similar, and selection is solely based on different character values. (These character values acting like runtime identifiers for the operations)
A better solution would build in some kind of relationship between all the operations, and tag each one with their character value identifier.


The conversion operations
Unfortunately, functions in C++ are like second-class citizens - You can only do two things with them, call them, or take their address. Taking the address of a function and storing it for later use may be of limited worth, but hardly elegant, and doesn't really build a very tight relationship between the operations.

The better alternative is to create a Functor or Function Object - that is, an object which behaves like a function. A function object is an instance of a class which has a Do Something method. That method can be anything, but for each distinct operation, a seperate class is needed.

Here's a rundown of the three operations as they stand, completely unrelated to each another as far as C++ is concerned.
std::string to_hex(int i)
{
	std::stringstream ss;
	ss << std::hex << i;
	return ss.str();
}

std::string to_oct(int i)
{
	std::stringstream ss;
	ss << std::oct << i;
	return ss.str();
}

std::string to_bin(int i)
{
	std::bitset< sizeof(i) * CHAR_BIT > bits(i);
	std::stringstream ss;
	ss << bits;
	return ss.str();
}




Function relationships
In order to build a relationship between anything in C++, some common ground is needed. Looking closely at the way these functions are called, It should be pretty clear that all the operations have several features in common; They all take a single int parameter, and they all return a string.
- In fact, aside from the function names, the signatures are identical. This is ideal, because now the functions can all be rewritten within functor classes, and related using a general-case class that exhibits all these common features. (The general-case class will be called converter in this example).

class converter
{
public:
	virtual std::string convert(int) = 0;
}; 


The convert signature is the all-purpose signature which generalises all the operations in the program; For this reason it is declared a pure virtual function. That is, a function which on its own, cannot do anything meaningful, and will rely on derived classes to provide a valid implementation.
- All derived classes must override the convert method - Think of this as a sort of 'contractual obligation' on the part of any class which derives from converter. The compiler will fire out an error towards any class that does not meet this obligation

- This being the case, it is given that converter must be an abstract base class; a class which cannot meaningfully represent objects on its own.



Specialisation
All functors must have a "do something" method - in this case, that method is called convert. It exhibits the common features of the conversion functions; a return type of string and a single int parameter. This is the framework upon which the operations will be written, as specialised derived classes of converter, which all have specialised implementations of the convert method depending on their behaviour.

Specialisation has another name in Object-oriented design - inheritance. The specialised functor classes will all 'inherit' from the abstract base class converter, thus the relationship between the operations is established through the base class.
class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
}; 



Fitting the pieces together
The command pattern structure is complete, but its still not clear how this helps streamline the selection process; the operations still need to be tied to their identifiers. A kind of dictionary is needed, whereby some user-supplied value can be automatically resolved to its corresponding operation without the use of a switch or an if/else block

The C++ Standard Template Library provides an ideal facility, designed for such situations where 'dictionaries' are needed - the <map> library is capable of mapping almost any value to any other value or object of a different type with ease. The STL map is known as an associative container because of its ability to associate values to objects of a certain type.

In this case, the lookup value or key value will be a char, but the individual operations are now tucked away in their own classes, each of a distinct, different type. It would be no good to pick one of these types as the associated type, since whichever one is used, the others would not be able to fit.
- The only choice left is the abstract base class, however, the base class cannot be instantiated, nor can the base class hold any of the operations themselves. This means that the map will not be able to physically hold the functors, but must instead hold pointers - the functors themselves will need to be created seperately.
	std::map<char, converter*> dict;
	dict.insert( std::make_pair( 'B', new bin_converter ) );
	dict.insert( std::make_pair( 'O', new oct_converter ) );
	dict.insert( std::make_pair( 'H', new hex_converter ) );



Now the character identifiers and their operations are neatly tied together in a dictionary object. Instead of the switch block from the original program, the selection process now looks like this
	std::map<char, converter*>::const_iterator iter;
	iter = dict.find( toupper(x) );
	if( iter != dict.end() )
		output = iter->second->convert( num );
	else
		output = "Invalid";




Wrapping it up
Perfect? Not quite. Everything is peachy from a functionality point of view; dynamic binding is more than capable of handling the selection process, and the dictionary is completely extensible. However, the dictionary is using dynamically allocated memory, which means the programmer must be careful not to "leak" the functors. Memory leaks are a big 'no-no' in software development, so its appropriate that the command pattern uses a technique to ensure that the dictionary is capable of cleaning up after itself, without the programmer needing to do anything else.

Handling dynamically allocated memory is such a commonly recurring issue, that the next version of the C++ standard will include a feature known as 'Automatic garbage collection' to handle it. For now though, there are idioms available which help programmers prevent memory leaks. The idiom needed here is known as RAII (Resource Acquisition Is Initialisation), though its name is unimportant, the technique is simple and efficient at cleaning up unused memory from the heap.

To facilitate the RAII idiom, the dictionary will be wrapped up inside its own class, which will have a destructor defined. The destructor can delete all of its allocated functors when a dictionary object is destroyed.
- Since the dictionary map is going to be locked up inside a class, it would also make sense to provide a lookup method for the user to interact with the dictionary. (The lookup method will follow on the same logic as the selection process shown above)
class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		// Populate the dictionary with converter operations.
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};



For anyone reading this code who has spotted that converter does not possess a virtual destructor, the class is actually well-formed, since none of the derived classes have destructors either. But since convert is already a virtual method, then for the sake of extensibility and safety, it would be a good idea to add an empty virtual destructor to the converter class, so not to fall foul of one of C++'s more subtle "gotcha's".


Finally
The complete, working version of the integer base conversion program using the command pattern, including an example in main() of how the example 'command dictionary' may be used to convert a number's representation.

#include <iostream>
#include <string>
#include <bitset>
#include <sstream>
#include <map>
#include <cctype>

class converter
{
public:
	virtual std::string convert(int) = 0;
	virtual ~converter() {}
};

class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
};

class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};

int main()
{
	using namespace std;

	int num = 1234; 
	char ch = 'h';
	string output = "";
	dictionary dict;

	converter* con = dict.lookup( ch );

	if( con != NULL )
		output = con->convert( num );
	else
		output = "Invalid";

	cout << "Result: " << output;
} 



Summary
The command pattern is a powerful and flexible design idiom, commonly used in Graphical User Interface design to handle events and commands issued by a user. Design patterns are intended to allow greater modularity when designing programs, reducing the dependencies placed on any given block of code.

Among other things, this article should demonstrate that object oriented design is not about reducing the number of lines of code in a program, but about allowing problems to be broken down into sub-problems, producing small, reusable modules at every step along the way. Ultimately this approach should pave the way for larger problems to be tackled more easily.



References
Design Patterns: Elements of re-usable Object Oriented Software - Gamma et al.
The C++ Programming Language Special Ed. - Bjarne Stroustrup
Thinking in C++ Vol. 2 - Bruce Eckel



Practise Exercises
Think you understand the command pattern? Challenge yourself!

(1) Using the command pattern framework above to add an operation that outputs a string with the number's digits in reverse order.

(2) Create a command pattern framework which simulates a simple calculator, with operations such as add, subtract and multiply.

Was This Post Helpful? 0
  • +
  • -

#9 sssunny  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 31-July 09

Posted 31 July 2009 - 03:18 AM

View PostBench, on 29 Nov, 2007 - 12:39 PM, said:

Design Patterns in C++ - The Command Pattern

Preface
This article is aimed at readers at a more advanced level of understanding of the C++ language, and assumes familiarity with C++'s object oriented capabilities, as well as some understanding of the Standard Template Library. This article is intended for anybody who wishes to explore new techniques of object oriented software design and problem solving. The example shown takes a fairly common programming problem and completely re-factors the 'traditional' structured procedural solution into an object-oriented solution.


Introduction
Design Patterns are a language-independent idea, which harness the power of object-oriented programming languages, allowing commonly recurring problems to be tackled in some surprising and elegant ways. Ideally, this article probably belongs in a language-neutral zone dedicated to computer science theory, but the implementation of design patterns can vary as much as the languages in which they are used.

This article focuses on C++, and specifically, the Command Pattern, as pioneered by the "Gang Of Four" (GoF) in their book "Design Patterns: Elements of re-usable Object Oriented Software".
http://www.amazon.co...l/dp/0201633612

The Command Pattern is a particularly flexible and powerful design pattern, able to streamline decision making and selection by doing something that most object-oriented languages don't naturally do - treating operations or commands as objects in their own right, allowing related commands to be grouped together and picked out at runtime, without a tedious If/then/else structure.


A common problem
This one should be familiar to all computer science students - create a program which sends the user a list of options, such as a vending machine, a calculator, a radio station selector, etc. and performs a different task dependent on the user's choice. The command pattern is not concerned with the "ask a user" part, but what happens once the user has made his/her selection.

Consider a program which displays a number in either Hexadecimal, Octal or Binary representation, based on the user's choice. The obvious solution may be to write several functions which perform the conversion, and a switch-based menu to make a decision of which function to call.
	string output;
	switch( toupper(x) )
	{
	case 'O':   output = to_oct(num);
				break;
	case 'H':   output = to_hex(num);
				break;
	case 'B':   output = to_bin(num);
				break;
	default:	output = "invalid";
	} 

The code works, but its design is rather rigid. Every time the operations change, the switch block needs to be modified. At the moment, operations are just functions which exist completely independently of each another, even though they're all in fact fairly similar, and selection is solely based on different character values. (These character values acting like runtime identifiers for the operations)
A better solution would build in some kind of relationship between all the operations, and tag each one with their character value identifier.


The conversion operations
Unfortunately, functions in C++ are like second-class citizens - You can only do two things with them, call them, or take their address. Taking the address of a function and storing it for later use may be of limited worth, but hardly elegant, and doesn't really build a very tight relationship between the operations.

The better alternative is to create a Functor or Function Object - that is, an object which behaves like a function. A function object is an instance of a class which has a Do Something method. That method can be anything, but for each distinct operation, a seperate class is needed.

Here's a rundown of the three operations as they stand, completely unrelated to each another as far as C++ is concerned.
std::string to_hex(int i)
{
	std::stringstream ss;
	ss << std::hex << i;
	return ss.str();
}

std::string to_oct(int i)
{
	std::stringstream ss;
	ss << std::oct << i;
	return ss.str();
}

std::string to_bin(int i)
{
	std::bitset< sizeof(i) * CHAR_BIT > bits(i);
	std::stringstream ss;
	ss << bits;
	return ss.str();
}




Function relationships
In order to build a relationship between anything in C++, some common ground is needed. Looking closely at the way these functions are called, It should be pretty clear that all the operations have several features in common; They all take a single int parameter, and they all return a string.
- In fact, aside from the function names, the signatures are identical. This is ideal, because now the functions can all be rewritten within functor classes, and related using a general-case class that exhibits all these common features. (The general-case class will be called converter in this example).

class converter
{
public:
	virtual std::string convert(int) = 0;
}; 


The convert signature is the all-purpose signature which generalises all the operations in the program; For this reason it is declared a pure virtual function. That is, a function which on its own, cannot do anything meaningful, and will rely on derived classes to provide a valid implementation.
- All derived classes must override the convert method - Think of this as a sort of 'contractual obligation' on the part of any class which derives from converter. The compiler will fire out an error towards any class that does not meet this obligation

- This being the case, it is given that converter must be an abstract base class; a class which cannot meaningfully represent objects on its own.



Specialisation
All functors must have a "do something" method - in this case, that method is called convert. It exhibits the common features of the conversion functions; a return type of string and a single int parameter. This is the framework upon which the operations will be written, as specialised derived classes of converter, which all have specialised implementations of the convert method depending on their behaviour.

Specialisation has another name in Object-oriented design - inheritance. The specialised functor classes will all 'inherit' from the abstract base class converter, thus the relationship between the operations is established through the base class.
class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
}; 



Fitting the pieces together
The command pattern structure is complete, but its still not clear how this helps streamline the selection process; the operations still need to be tied to their identifiers. A kind of dictionary is needed, whereby some user-supplied value can be automatically resolved to its corresponding operation without the use of a switch or an if/else block

The C++ Standard Template Library provides an ideal facility, designed for such situations where 'dictionaries' are needed - the <map> library is capable of mapping almost any value to any other value or object of a different type with ease. The STL map is known as an associative container because of its ability to associate values to objects of a certain type.

In this case, the lookup value or key value will be a char, but the individual operations are now tucked away in their own classes, each of a distinct, different type. It would be no good to pick one of these types as the associated type, since whichever one is used, the others would not be able to fit.
- The only choice left is the abstract base class, however, the base class cannot be instantiated, nor can the base class hold any of the operations themselves. This means that the map will not be able to physically hold the functors, but must instead hold pointers - the functors themselves will need to be created seperately.
	std::map<char, converter*> dict;
	dict.insert( std::make_pair( 'B', new bin_converter ) );
	dict.insert( std::make_pair( 'O', new oct_converter ) );
	dict.insert( std::make_pair( 'H', new hex_converter ) );



Now the character identifiers and their operations are neatly tied together in a dictionary object. Instead of the switch block from the original program, the selection process now looks like this
	std::map<char, converter*>::const_iterator iter;
	iter = dict.find( toupper(x) );
	if( iter != dict.end() )
		output = iter->second->convert( num );
	else
		output = "Invalid";




Wrapping it up
Perfect? Not quite. Everything is peachy from a functionality point of view; dynamic binding is more than capable of handling the selection process, and the dictionary is completely extensible. However, the dictionary is using dynamically allocated memory, which means the programmer must be careful not to "leak" the functors. Memory leaks are a big 'no-no' in software development, so its appropriate that the command pattern uses a technique to ensure that the dictionary is capable of cleaning up after itself, without the programmer needing to do anything else.

Handling dynamically allocated memory is such a commonly recurring issue, that the next version of the C++ standard will include a feature known as 'Automatic garbage collection' to handle it. For now though, there are idioms available which help programmers prevent memory leaks. The idiom needed here is known as RAII (Resource Acquisition Is Initialisation), though its name is unimportant, the technique is simple and efficient at cleaning up unused memory from the heap.

To facilitate the RAII idiom, the dictionary will be wrapped up inside its own class, which will have a destructor defined. The destructor can delete all of its allocated functors when a dictionary object is destroyed.
- Since the dictionary map is going to be locked up inside a class, it would also make sense to provide a lookup method for the user to interact with the dictionary. (The lookup method will follow on the same logic as the selection process shown above)
class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		// Populate the dictionary with converter operations.
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};



For anyone reading this code who has spotted that converter does not possess a virtual destructor, the class is actually well-formed, since none of the derived classes have destructors either. But since convert is already a virtual method, then for the sake of extensibility and safety, it would be a good idea to add an empty virtual destructor to the converter class, so not to fall foul of one of C++'s more subtle "gotcha's".


Finally
The complete, working version of the integer base conversion program using the command pattern, including an example in main() of how the example 'command dictionary' may be used to convert a number's representation.

#include <iostream>
#include <string>
#include <bitset>
#include <sstream>
#include <map>
#include <cctype>

class converter
{
public:
	virtual std::string convert(int) = 0;
	virtual ~converter() {}
};

class hex_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::hex << i;
		return ss.str();
	}
};

class oct_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::stringstream ss;
		ss << std::oct << i;
		return ss.str();
	}
};

class bin_converter : public converter
{
public:
	std::string convert(int i)
	{
		std::bitset< sizeof(i) * CHAR_BIT > bits(i);
		std::stringstream ss;
		ss << bits;
		return ss.str();
	}
};

class dictionary
{
	std::map<char, converter*> dict;
public:
	dictionary()
	{
		dict.insert( std::make_pair( 'B', new bin_converter ) );
		dict.insert( std::make_pair( 'O', new oct_converter ) );
		dict.insert( std::make_pair( 'H', new hex_converter ) );
	}

	converter* lookup(char x)
	{
		std::map<char, converter*>::const_iterator iter;
		iter = dict.find( toupper(x) );
		if( iter != dict.end() )
			return iter->second;
		else
			return NULL;
	}

	~dictionary()
	{
		while( dict.begin() != dict.end() )
		{
			delete dict.begin()->second;
			dict.erase( dict.begin() );
		}
	}
};

int main()
{
	using namespace std;

	int num = 1234; 
	char ch = 'h';
	string output = "";
	dictionary dict;

	converter* con = dict.lookup( ch );

	if( con != NULL )
		output = con->convert( num );
	else
		output = "Invalid";

	cout << "Result: " << output;
} 



Summary
The command pattern is a powerful and flexible design idiom, commonly used in Graphical User Interface design to handle events and commands issued by a user. Design patterns are intended to allow greater modularity when designing programs, reducing the dependencies placed on any given block of code.

Among other things, this article should demonstrate that object oriented design is not about reducing the number of lines of code in a program, but about allowing problems to be broken down into sub-problems, producing small, reusable modules at every step along the way. Ultimately this approach should pave the way for larger problems to be tackled more easily.



References
Design Patterns: Elements of re-usable Object Oriented Software - Gamma et al.
The C++ Programming Language Special Ed. - Bjarne Stroustrup
Thinking in C++ Vol. 2 - Bruce Eckel



Practise Exercises
Think you understand the command pattern? Challenge yourself!

(1) Using the command pattern framework above to add an operation that outputs a string with the number's digits in reverse order.

(2) Create a command pattern framework which simulates a simple calculator, with operations such as add, subtract and multiply.



Awesome tutorial.............but if you see closly in the dictionary class it is just returning you object corrosponding to your option selected ie: o,e,h etc.It means class dictionary is behaving as a factory class which is returning you object and you are calling approprate class corrosponding to that.It looks as Factory pattern???
Was This Post Helpful? 0
  • +
  • -

#10 eker676  Icon User is offline

  • Software Engineer
  • member icon

Reputation: 378
  • View blog
  • Posts: 1,833
  • Joined: 18-April 09

Posted 13 December 2009 - 11:19 AM

Wow, nice tutorial. (For lack of a better phrase) I like the linking of the functions to a specific character.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1