Strategy Pattern C++ - c++

I want implement the strategy pattern in C++ but I have a doubt. Alwyas the strategy patterns examples are than follow code (in C#). I want modify the client, i.e MainClass, such that choose the concrete strategy will be dynamic way.
For example, passing the strategy name by the args[] parameters of the main method. How I will be able to implement this without modify the properties of this pattern?.
namespace StrategyPatterns
{
// Interface definition for a Sort algorithm
public interface ISort
{
void Sort(List<string> list)
}
// QuickSort implementation
public class CQuickSorter : ISort
{
void Sort(List<string> list)
{
// Here will come the actual imp
}
}
// BubbleSort
public class CBubbleSort : ISort
{
void Sort(List<string> list)
{
// The actual imp of the sort
}
}
public class Context
{
private ISort sorter;
public Context(ISort sorter)
{
// We pass the context the strategy to use
this.sorter = sorter;
}
public ISort Sorter
{
get{return sorter;)
}
}
public class MainClass
{
static void Main()
{
List<string> myList = new List<string>();
myList.Add("Hello world");
myList.Add("Another item");
Contexto cn = new Contexto(new CQuickSorter());
cn.Sorter.Sort(myList);
cn = new Contexto(new CBubbleSort());
cn.Sorter.Sort(myList);
}
}
}

We do not have reflection in C++, that is the concept you need to get this to work right.. The alternative that I can think of, is to make a factory method as below..
ISort* CreateSorter(SortType type)
{
switch (type){
case QUICK_SORT: return new CQuickSorter();
...
}
}
I use an enum for cleaner code, but you can change that into a string, as long as you are able to understand my basic point.

I would give the context class a templated factory function setSorter and handle the entire lifetime of the sorter objects internally.
class Interface { //this class and all sorting clases could be templated to be able to deal with sorting lists of different data types
std::unique_ptr<ISort> sorter_;
public:
Interface():sorter_(new CQuickSorter()){ //CQuickSorter is the default sorter
}
template<typename T>
setSorter(){ //one could also use perfect forwarding to pass arguments to T's constructor
sorter_.reset(new T());
}
void sort(std::list<string> &list){
sorter_->sort(list);
}
};
int main(){
std::list<int> li;
Interface cn;
cn.sort(li); //using a default sort
cn.setSorter<CBubbleSort>();
cn.sort(li); //using bubble sort
}

Related

How can I choose the algorithm of a code only once at the beginning in C++?

There are two different algorithms being used throughout the code. Which one is chosen is determined at runtime by a parameter (e.g. true or false). I do not want to use if-statements each time the algorithm comes up.
So instead of writing the following every time
if (parameter==true)
algorithmOne();
else
algorithmTwo();
I want to set the algorithm at the beginning, like
if (parameter==true)
algorithm()=algorithmOne();
else
algorithm()=algorithmTwo();
and only use 'algorithm()' from this point forward.
How can I choose the algorithm at the beginning depending on a parameter after the code is already compiled?
Edit:
How do you do that within the constructor of a class (since a pointer-to-member function is no regular pointer)? As both algorithms rely on member variables and functions of this class, it is inconvenient to derive a new class.
Solution:
This could be solved with a virtual function and derived classes.
class Base
{
public:
Base();
virtual void algorithm() = 0;
~Base();
protected:
double d;
int i;
...
}
class DerivedOne : public Base
{
public:
DerivedOne() : Noise() {};
void algorithm() override;
~DerivedOne();
};
Base *b;
if (parameter==true)
{
b = new DerivedOne();
}
else
{
b = new DerivedTwo();
}
Then the function can be called with:
b->algorithm();
And deleted with:
delete b;
This may not be the best way but it seems to work for me. See answers and comments.
You're almost there:
auto algorithm = parameter ? algorithmOne : algorithmTwo.
No (), you're not trying to call any function here.
The answer you are looking for is likely a function/method pointer.
The syntax for a function pointer is as follows:
typedef void (*MyFunctionPointer)();
MyFunctionPointer *algorithm;
void function(bool parameter)
{
if (parameter)
algorithm = &myFirstAlgo;
else
algorithm = &mySecondAlgo;
}
void anotherFunction()
{
algorithm();
}
Please note that this approach works for C, C++03 and C++11. If you want to use auto on the global scope, you need to give it a default value.
The object-oriented way of doing this would be to define a base class with the algorithm interface:
class AlgorithmBase
{
public:
virtual void algorithm() = 0;
virtual ~AlgorithmBase() {} // virtual destructor may be needed
};
Then implement classes for the different algorithm implementations:
class AlgorithmOne: public AlgorithmBase
{
public:
virtual void algorithm();
};
void AlgorithmOne::algorithm()
{
...
}
and similarly for AlgorithmTwo and other implementations.
Now, you can define a pointer to an algorithm object containing the selected implementation and use that whenever the algorithm shall be executed:
AlgorithmBase *algorithm = 0;
if(parameter)
{
algorithm = new AlgorithmOne();
}
else
{
algorithm = new AlgorithmTwo();
}
...
algorithm->algorithm(); // Call the selected algorithm
...
delete algorithm; // Destroy algorithm instance before exiting

C++ equivalence to Java's anonymous class

I am working on translating some Java code to C++.
In Java, we can create object from anonymous class, using existing constructor, and overriding some methods. E.g.,
class X {
public X(int value) {...}
public void work() {....}
}
void main(String[] args) {
X entity = new X(5) {
public void work() { /* Something else */ }
};
}
In C++, I know I can create anonymous class as following:
class X {
public:
virtual void work() {...}
}
class : public X {
public:
void work() {....}
} obj;
But C++ does not allow constructor in anonymous class, and it does not allow extending from object (e.g., the new X(5) { public void work() {} } like what Java allows.
How can I write similar code in C++?
Update 03/07/2020 05:27 CDT
More context about the problem I am working on. I am implementing aggregation function of a in-memory SQL database, and use the following class to represent an aggregation field:
class AggField {
public:
AggField(int colIndex);
virtual void reduce(DataRow&) = 0;
virtual double output() = 0;
}
For each type of aggregation, e.g., avg, min/max and sum, I have a subclass. For example
class Avg : public AggField {
private:
int counter_;
double value_;
public:
Avg(int colIndex) : AggField(colIndex), counter_(0), value_(0) {};
void reduce(DataRow&) override {
value_ += row[colIndex].doubleval();
counter_ += 1;
}
double output() override {
return value_ / counter_;
}
}
class Sum : public AggField {
.....
}
When processing a table, I will write the following
Table table = ...
auto agg_opr = Agg({
new Sum(0),
new Avg(1)
});
agg_opr.agg(table);
which does a sum on column 0, and average on column 1.
Sometimes(rare) I need to process more than one input columns. For example, doing a sum of col1 * (1 + col2). Instead of creating a new subclass of AggField, I would like to write something similar to:
Table table = ...
auto agg_opr = Agg({
new Sum(0) {
void reduce(DataRow& row) {
value_ += row[0].doubleval() * (1 + row[1].doubleval());
}
},
new Avg(1),
new Max(1)
});
agg_opr.agg(table);
I can't say that I know how to write idiomatic Java but I'm guessing that this pattern in Java is an alternative to lambdas in C++. I remember using an anonymous class long ago when I was working with Swing. I think I did something like this:
button.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// ...
}
});
This is sugar for inheriting from a class and overriding a method. Doing precisely that is not really how I would like to attach an event listener in C++. I'd prefer to do this:
button.addMouseClickListener([](const MouseEvent &e) {
// ...
});
In the case of an event listener, the closure would need to be stored in a std::function or something similar. This has roughly the same performance as a virtual call.
I don't really know much about where you're using this class but if you need to store it aside (like an event listener or something) then declaring the class the long way or using std::function are probably the cleanest options. If you don't need to store it aside (like a policy for an algorithm) then you could use a functor. Of course, you can store aside a functor but it takes a bit of template machinery and probably isn't worth it (although it does have more flexibility).
struct MyPolicy {
int doSomething(int i) {
return i * 3;
}
double getSomething() const {
return d;
}
double d;
};
template <typename Policy>
void algorithm(Policy policy) {
// use policy.doSomething and policy.getSomething...
}
Using a functor or lambda with a template has much better performance than using virtual functions. In the above example, the compiler can and probably will inline the calls to doSomething and getSomething. This isn't possible with virtual functions.
If I knew more about the real problem that you're trying to solve then I might be able to write a more specific and helpful answer.
After seeing the updated question I have another suggestion. That would be to create a subclass for custom aggregate functions. Of course, this has plenty of limitations.
template <typename Func>
class CustomAgg : public AggField {
public:
CustomAgg(int colIndex, Func func)
: AggField{colIndex}, func{func} {}
void reduce(DataRow &row) override {
func(value, row);
}
double output() override {
return value;
}
private:
Func func;
double value = 0.0;
// could add a `count` member if you want
};
auto agg_opr = Agg({
new CustomAgg{0, [](double &value, DataRow &row) {
value += row[0].doubleval() * (1 + row[1].doubleval());
}},
new Avg(1),
new Max(1)
});
Honestly, I think the best solution for you is to not try to implement a Java feature in C++. I mean, if you need to handle multiple columns in some specific operation then create a class just for that. Don't take any shortcuts. Give it a name even though you might only use it in one place.
C++ has anonymous namespaces, which effectively lets you create classes that are completely isolated to the translation units they're declared in:
namespace {
class X {
public:
X(int) { /* ... */ } // Ok to have a constructor
void work();
};
}
int main(int argc, char **argv)
{
X entity{5};
// ...
}
Now, you have to declare them in global scope, you can't declare them in inner scope. You'll also need to give these classes normal names that you can reference them by in the same translation unit; but for all practical purposes they're completely anonymous and inaccessible from other translation units. Another translation unit can declare its own anonymous class "X", and there won't be any conflicts.
You can use anonymous classes in all other normal ways, subclass them, etc... You can create an anonymous class that's a subclass of a regular, non-anonymous class, which gets you pretty close to what Java does, here.
Some compilers also offer extensions where you can declare classes in inner scopes, and they'll also work very similar to anonymous namespaces, but that's going to be a compiler-specific extension.

Is a big switch block unavoidable in C++ due to lack of reflection [duplicate]

This question already has answers here:
Is there a way to instantiate objects from a string holding their class name?
(12 answers)
Closed 9 years ago.
Assume I have a hierarchy of classes:
class Shape {
};
class Circle : public Shape {
}
class Square : public Shape {
}
... hundreds of other shapes continue on...
When given the name of a shape class as a string, I need to instantiate objects of that class.
In java, I can do something like this (pseudo code!)
Shape createShape(String name) {
return new Class.forName(name);
}
But in C++, I have to do this: (pseudo code!)
Shape * createShape(const string &name) {
if (name.compare("Circle") == 0) {
return new Circle();
}
else if (name.compare("Square") == 0) {
return new Square();
}
else if ... //hundreds of else if continues, one for each shape
}
Is there any better way in C++ to handle situation like this?
It's avoidable using the factory pattern, but you still need a bunch of boilerplate code to get off the ground. For example:
// Class factory functions -- these could also be inlined into their respective
// class definitions using a macro
Shape *createCircle() { return new Circle(); }
Shape *createSquare() { return new Square(); }
// etc.
// Create a map from type name to factory
typedef std::map<std::string, Shape *(*)()> ShapeFactoryMap;
ShapeFactoryMap factoryMap;
factoryMap["Circle"] = &createCircle;
factoryMap["Square"] = &createSquare;
// etc.
Then, when you want to instantiate an object, you can do this:
ShapeFactoryMap::iterator factory = factoryMap.find("Circle");
if (factory != factoryMap.end())
{
Shape *circle = factory->second(); // Creates a Circle instance
...
}
else
{
// Handle error
}
Whether this is better than just doing a series of if/else... string comparisons is not clear, since it depends on what exactly you're doing to be doing with this.
I second Adam Rosenfield's solution using maps. However, a lower level interface to get your higher level functionality is to use a dlsym() lookup.
Assume that your generic Shape interface lies in the file Shape.hpp and has the following form:
class Shape {
public:
virtual ~Shape () {}
//...virtual methods
virtual void draw () const = 0;
};
template <typename DERIVED>
class ShapeBridge : public Shape {
public:
static Shape * create () { return new DERIVED; }
};
struct ShapeFactory {
Shape * (*create) ();
};
Suppose you wanted to add a new shape dynamically by creating a new shared object, and then linking it dynamically into your existing running executable. Then, you can now create an abstract factory of sorts, which uses dynamic loading of shared objects to obtain the concrete factory functions:
#include <string>
#include <map>
#include <dlfcn.h>
struct ShapeCreator {
void *dlhandle_;
void *factory_;
ShapeCreator () : dlhandle_(0), factory_(0) {}
void open (std::string libname) {
dlhandle_ = dlopen(libname.c_str(), RTLD_LAZY);
factory_ = dlsym(dlhandle_, "factory");
}
void close () { if (dlhandle_) dlclose(dlhandle_); }
ShapeFactory * factory () const {
return static_cast<ShapeFactory *>(factory_);
}
static Shape * create (std::string name) {
static std::map<std::string, ShapeCreator> lookup;
static std::string dir = "./";
if (lookup[name].factory() == 0) {
lookup[name].open(dir + name + ".so");
}
return lookup[name].factory()->create();
}
};
Your shared object could have the following implementation:
// gcc -fPIC -shared -Wl,-export-dynamic -o Circle.so Circle.cpp -lc
#include "Shape.hpp"
#include <iostream>
class Circle : public ShapeBridge<Circle> {
public:
//..
void draw () const { std::cout << "I am a circle.\n"; }
};
extern "C" {
ShapeFactory factory = { Circle::create };
}
Then to dynamically create the shape:
Shape *s = ShapeCreator::create("Circle");
s->draw();
Of course, the example is a little more interesting if it actually obtained its name dynamically (like from a configuration file, or from a user input).
The main difference is that unlike Java, C++ doesn't have an in-built function like forName(String), which does the task for you. In C++ you have to implement it.
Now it's important how you do that stuff. The proposed way of switch/case is one way, which is straight forward but lengthy way. You can automate the things:
(1) First introduce an intermediate template class, which creates an object, so that you don't have to implement method for each and every class.
template<class Derived>
class ShapeCreator : public Shape { // This class automates the creations
public:
static Shape* Create () {
new Derived(); // Assuming that no-argument default constructor is avaialable
}
};
class Circle : public ShapeCreator<Circle> {
};
class Square : public ShapeCreator<Square> {
};
//... and so on
(2) Now inside the class Shape, introduce one static std::map, which holds a handle to every derived class.
class Shape {
public:
typedef std::map<std::sting, Shape* (*)()> ShapeMap;
static ShapeMap s_ShapeMap;
static Shape* Create (const std::string name) {
ShapeMap::iterator it = s_ShapeMap.find(name);
if(it == s_ShapeMap.end())
return 0;
it->second();
}
};
(3) Populating s_ShapeMap has to be done statically, you can choose to do it before the main() is called (be careful while doing this) or as the first function inside the main(). Use preprocessor trick to automate the things:
#define INIT(SHAPE) Shape::s_ShapeMap[#SHAPE] = &SHAPE::Create
Shape* InitializeShapeMap () {
INIT(Circle);
INIT(Square);
INIT(Triangle);
// ...
}
#undef INIT
Whenever any new shape is introduced, then just add it as an INIT inside the function.
C++ is a 'class based' language which means the structure of a class is only known at compile time. Hence you cannot generate a type at runtime.
It's better to avoid that sort of class instanciation unless you only know the class name at runtime.
If need to do that at large scale, have a look at third-party code generators such as jinja.
It'll help you create a factory off a template and a given mapping "string" -> "class name".
There's no way to do what you want the way it is in Java, but there are ways to make it slightly less painful than a giant switch statement. You will need some kind of factory. Personally I like to use something along these lines:
class ShapeBase
{
};
template<class TShape>
class Shape: public ShapeBase
{
public:
typedef TShape shape_type;
template< class TFactory >
static void registerClass(TFactory* factory)
{
factory->registerShape(shape_type::name(), [](){ return new shape_type(); });
}
};
class Circle: public Shape<Circle>
{
public:
static const char* name() { return "Circle"; }
};
class Square: public Shape<Square>
{
public:
static const char* name() { return "Square"; }
};
class ShapeFactory
{
private:
typedef std::function<ShapeBase*()> shape_creator;
std::map<std::string,shape_creator> _creators;
public:
ShapeFactory()
{
registerShapes();
}
void registerShapes()
{
Square::registerClass(this);
Circle::registerClass(this);
}
void registerShape( const std::string& name, shape_creator creator )
{
_creators[name] = creator;
}
ShapeBase* create(const std::string& name)
{
return _creators[name]();
}
};
int main( int argc, char** argv )
{
ShapeFactory factory;
ShapeBase* circle = factory.create("Circle");
ShapeBase* square = factory.create("Square");
return 0;
}
If you can get away with defining all of your Shape objects in an executable component or dynamic library, rather than a static library, then there are tricks that you can use to auto-register your classes with a singleton factory, but I think it's a better idea to do it this way and avoid the singleton.
There is no support for what you are asing in the language. Nevertheless you can use the following pattern to streamline your design:
class Shape
{
Shape *CreateShape(const char *name)
{
// Iterate single linked list of known derived classes.
Node *item = ListOfDerivedClasses;
while (item != NULL)
{
if (strcmp(item->name, name) == 0)
return item->factory();
item = item->next;
}
}
typedef Shape *CreateShapeInstance();
struct Node
{
char *name;
CreateShapeInstance *factory;
Node *next;
Node(char *n, CreateShapeInstance *f)
{
name = n; factory = f;
next = Shape::ListOfDerivedClasses;
Shape::ListOfDerivedClasses = this;
}
};
static Node *ListOfDerivedClasses;
};
class Circle : public Shape
{
static Shape *CreateInstance() { return new Circle(); }
}
static Shape::Node circle_info("Circle", Circle::CreateInstance);
The idea is that the single linked list that contains only static elements is created during initialization of static objects and it is never modified after that. This design allows adding derived classes without modifying the base class while CreateShape in the base class can create any derived class that registered itself in the list.

container pattern with specialized children

I have several specialized classes. for example
class Transition_Matrix : public Transition
{
SetMatrix(Matrix* pStartMatrix);
};
class Transition_Vector : public Transition
{
SetVector(Vector* pStartVector);
}
class Transition_Container : public Transition
{
}
I would like to do call SetVector() or SetMatrix() on Animate_Container without declaring the functions for each type of object that needs to be set. For example, I do not want to declare Animate_Container as follows...
class Transition_Container : public Transition
{
SetMatrix(Matrix* pStartMatrix);//loops through all children calling SetMatrix
SetVector(Vector* pStartVector);//loops through all children calling SetVector
}
I don't want Animate_Container to know which children it has. But I want the convenience of calling these functions on the container so I do not have to search through the children and figure out which functions I should call when "transitioning" a matrix or a vector.
What is the correct pattern that I should use here?
Basically I want to set a matrix or vector on the root container and have it propogate down to each child than may want to use it.
ideas?
A basic composite pattern will suffice here. To implement this you declare the member functions as virtual in the base class Transition. This will allow you to maintain a list of Transition objects in Transition_Container, iterate through the list and call the appropriate member function.
#include <vector>
class Transition
{
public:
// default impementation that does nothing
virtual void SetMatrix(Matrix*) {}
};
class Transition_Container : public Transition
{
std::vector<Transition*> transitions_;
public:
virtual void SetMatrix(Matrix* pStartMatrix)
{
for(std::vector<Transition*>::iterator it = transitions_.begin();
it != transitions_.end();
++it)
{
(*it)->SetMatrix(pStartMatrix);
}
}
};
If you do not want Transition to know about the various data types that can be used you can use boost:any and boost:any_cast. This is very similar to the suggestion above but removes the dependency of Matrix and Vector from Transition and places the responsibility of dealing with different types on the implementation of classes that derive from it. I only recommend doing this if there is some requirement that absolutely prevents Transition from knowing about the Matrix and Vector types.
#include <vector>
#include <boost/any.hpp>
class Transition
{
public:
// default impementation that does nothing
virtual void SetValue(boost::any&) {}
};
class Transition_Matrix : public Transition
{
virtual void SetValue(boost::any& value)
{
try
{
Matrix *matrix = boost::any_cast<Matrix*>(value);
// do stuff
}
catch(const boost::bad_any_cast &)
{
return;
}
}
};
class Transition_Container : public Transition
{
std::vector<Transition*> transitions_;
public:
template<Arg>
void SetValueT(Arg* arg)
{
boost::any value = arg;
SetValue(value);
}
virtual void SetValue(boost::any& value)
{
for(std::vector<Transition*>::iterator it = transitions_.begin();
it != transitions_.end();
++it)
{
(*it)->SetValue(value);
}
}
};
I recommend using shared_ptr or unique_ptr from Boost or the C++11 Standard Library for maintaining the list of Transition objects like so.
std::vector<std::shared_ptr<Transition>> transitions_;
I did not include this in the above example as I do not know if you are familiar with using this yet. IF you are not I suggest looking into it.

Creating dynamic type in C++

I'm writing a piece of generic software that will be loaded on to many different variants of the same basic hardware. They all have the same processor, but with different peripherals and their own functions that need to be carried out. The software will know which variant it should run by reading a hardware switch value.
Here's my current implementation in a nutshell:
class MyBase
{
public:
MyBase() { }
virtual run() = 0;
}
class VariantA : public MyBase
{
public:
VariantA () { }
virtual run()
{
// Run code specific to hardware Variant-A
}
}
class VariantB : public MyBase
{
public:
VariantB () { }
virtual run()
{
// Run code specific to hardware Variant-B
}
}
void main()
{
MyBase* variant;
uint_8 switchValue = readSwitchValue();
switch(switchValue)
{
case 0:
variant = new VariantA();
break;
case 1:
variant = new VariantB();
break;
}
variant->run();
}
Now this works just fine. I read the hardware value and use a switch statement to create the new corresponding class.
The problem is that there are a lot of variants I have to deal with. Currently about 15, with the potential to add another 20-30 in the near future. I have really come to despise switch statements that run for hundreds of lines, so I'm really looking for a better way to do this, probably through templates.
I want to be able to use my hardware value to look up a type and use that type to create my new object. Ideally when I add a new variant, I create the new class, add that class type to my lookup table with it's matching hardware value, and it's good to go.
Is this possible at all? What's a good solution here?
As stated, you make a factory, but not necessarily with naive switch statements. What you can do is make a template class to create the relevant object and dynamically add these to your factory.
class VariantinatorBase {
public:
VariantinatorBase() {}
virtual ~VariantinatorBase() {}
virtual std::unique_ptr<Variant> Create() = 0;
};
template< class T >
class Variantinator : public VariantinatorBase {
public:
Variantinator() {}
virtual ~Variantinator() {}
virtual std::unique_ptr<Variant> Create() { return std::make_unique<T>(); }
};
Now you have a class factory that allows you to register these.
class VariantFactory
{
public:
VariantFactory()
{
// If you want, you can do all your Register() calls in here, and even
// make the Register() function private.
}
template< uint8_t type, typename T >
void Register()
{
Register( type, std::make_unique<Variantinator<T>>() );
}
std::unique_ptr<Variant> Create( uint8_t type )
{
TSwitchToVariant::iterator it = m_switchToVariant.find( type );
if( it == m_switchToVariant.end() ) return nullptr;
return it->second->Create();
}
private:
void Register( uint8_t type, std::unique_ptr<VariantinatorBase>&& creator )
{
m_switchToVariant[type] = std::move(creator);
}
typedef std::map<uint8_t, std::unique_ptr<VariantinatorBase> > TSwitchToVariant;
TSwitchToVariant m_switchToVariant;
};
At the beginning of your program, create the factory and register your types:
VariantFactory factory;
factory.Register<0, VariantA>();
factory.Register<1, VariantB>();
factory.Register<2, VariantC>();
Then later, you want to call on it:
std::unique_ptr<Variant> thing = factory.Create( switchValue );
You are looking for a factory
http://www.oodesign.com/factory-pattern.html
A factory is a software module (a method, a class) whose sole purpose is to create the right object for the job. An example using a factory class:
class VariantFactory
{
MyBase* CreateObject(uint_8 value);
}
And the CreateObject method can be filled out to give you the type of object that you need.
In the case of a very small selection of objects with simple construction, a simple switch statement might suffice. As soon as you get a lot of objects or ones that require more detailed construction, a factory is quite useful.
I made this a comment; let's turn it into an answer:
Personally, I think a "switch/case" block to create the appropriate class is probably an optimal solution. Just put your case statement in a static "factory" method that returns a reference to the specific class. IMHO...
Here's a good example: factory method design pattern
Class Book : public Product
{
};
class Computer : public Product
{
};
class ProductFactory
{
public:
virtual Product* Make(int type)
{
switch (type)
{
case 0:
return new Book();
case 1:
return new Computer();
[...]
}
}
}
Call it like this:
ProductFactory factory = ....;
Product* p1 = factory.Make(0); // p1 is a Book*
Product* p2 = factory.Make(1); // p2 is a Computer*
// remember to delete p1 and p2
Note that in his most excellent response, smink also suggests some other design alternatives, too.
BOTTOM LINE: There's nothing inherently "wrong" with a switch/case block. Even for a switch with many case options.
IMHO...
PS:
This really isn't creating a "dynamic type". Rather, it's "creating a static type dynamically". That would be equally true if you used a template or an enum solution as well. But again - I vastly prefer the "switch/case".
Update: I am leaving my original solution here for posterity, but consider the solution provided by paddy to be superior and less error prone. With only a couple of slight improvements I think it's actually about as good as you can possibly get.
Consider this design:
class VariantA : public MyBase
{
static MyBase *CreateMachineInstance() { return new VariantA; }
};
class VariantB : public MyBase
{
static MyBase *CreateMachineInstance() { return new VariantB; }
};
Now, all you need is an std::map that uses a uint_8 as the key and maps it to a function pointer (returning MyBase). Insert the identifiers in the map (pointing each to the appropriate machine creation function) and then read the code and just use the map to find what machine you're using.
This is loosely based on a concept/pattern called a "factory" but may break slightly if your machine constructors require different arguments or you need to perform additional per-machine initialization/operations - and from what you mention it sounds like you might.
If that's the case, you can still use this pattern but you will have to make some tweaks and rearchitect things a bit but you will end up with something much cleaner and easier to augment and maintain.
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
template<class T,class T1>
class HeroHonda
{
private:
T millage;
T1 *options;
public:
HeroHonda() {
puts("constructed");
options=new T1[20];
strcpy(options,"Good millage,Powerstart");
millage=110;
}
virtual T features() {
cout<<options<<"millage is"<<millage<<endl;
return 1;
}
// virtual T Extrafeatures() = 0;
~HeroHonda() {
cout<<"destructor"<<endl;
delete [] options;
}
};
int main()
{
HeroHonda <int,char> *Ptr=new HeroHonda <int,char>;
Ptr->features();
delete Ptr;
}