How can I make a visitor pattern configurable in runtime? - c++

Well, as you know, the design pattern Visitor has a "problem" similar to Abstract Factory problem: the more visitable classes I made, the more specific "visit" methods must create.
In the case of an abstract factory I made a solution using prototype of a product to "configure" the factory:
factory.h
class ExtensibleFactory
{
public:
~ExtensibleFactory();
void insertProductType(const string &nome, IProductPrototype *product);
void removeProductType(const string &nome);
IProductPrototype *createProduct(const string &nome);
private:
map<string, IProductPrototype *> m_productsHash;
};
factory.cpp
#include "extensiblefactory.h"
#include "iproductprototype.h"
ExtensibleFactory::~ExtensibleFactory()
{
for(map<string, IProductPrototype *>::iterator iter = this->m_productsHash.begin(); iter != this->m_productsHash.end(); ++iter)
{
delete iter->second;
}
this->m_productsHash.clear();
}
void ExtensibleFactory::insertProductType(const string &nome, IProductPrototype *product)
{
this->m_productsHash.insert(make_pair(nome, product));
}
void ExtensibleFactory::removeProductType(const string &nome)
{
delete this->m_productsHash[nome];
this->m_productsHash.erase(nome);
}
IProductPrototype *ExtensibleFactory::createProduct(const string &nome)
{
if ( this->m_productsHash.find(nome) == this->m_productsHash.end() )
{
return 0;
}
return this->m_productsHash[nome]->clone();
}
main.cpp
SanduichePrototype *sanduiche = new SanduichePrototype;
CarroPrototype *carro = new CarroPrototype;
ExtensibleFactory *fabrica = new ExtensibleFactory;
fabrica->insertProductType("sanduba", sanduiche);
fabrica->insertProductType("automovel", carro);
IProductPrototype *carro1 = fabrica->createProduct("automovel");
IProductPrototype *carro2 = fabrica->createProduct("automovel");
IProductPrototype *sanduiche1 = fabrica->createProduct("sanduba");
IProductPrototype *sanduiche2 = fabrica->createProduct("sanduba");
Now, consider this visitor and its elements:
ivisitor.h
class ElementA;
class ElementB;
class IVisitor
{
public:
virtual void visit(ElementA *elementA) = 0;
virtual void visit(ElementB *elementB) = 0;
};
ielement.h
class IVisitor;
class IElement
{
public:
virtual void accept(IVisitor *visitor) = 0;
};
elementa.h
class ElementA : public IElement
{
public:
virtual void accept(IVisitor *visitor);
};
elementb.h
class ElementB : public IElement
{
public:
virtual void accept(IVisitor *visitor);
};
If I want to add more elements I will have to add more methods do IVisitor interface.
I wish to know if it's possible to "configure" a visitor in runtime, in other words, I want to know if there are any solution to emulate the act of adding more methods to the IVisitor interface by configuring it just like I did to Factory pattern and, if so, which will be the possible solutions.

The action (visitor) object you want to pass around to objects will have to have hardwired at least knowledge of some common base class whose functionality it can use, and then as I see it there's not much point in dynamically registering visitable classes, because you need a dynamic dispatch anyway, e.g. dynamic_cast, and with that the need to list all supported classes in the common visitor interface, disappears.
Consider first a slight refactoring of your visitor pattern code – except for generality and naming and access it's the same as your code:
// Static visitor pattern.
template< class Visitable >
class Visitor_
{
template< class > friend class Visitable_impl_;
private:
virtual void visit( Visitable& ) {}
};
class A;
class B;
class I_visitor
: public Visitor_<A>
, public Visitor_<B>
{};
class I_visitable
{
public:
virtual void accept( I_visitor& ) = 0;
};
template< class Visitable >
class Visitable_impl_
: public I_visitable
{
public:
void accept( I_visitor& v )
override
{
static_cast<Visitor_<Visitable>&>( v ) // Cast for access.
.visit( static_cast<Visitable&>( *this ) ); // Cast for overload res.
}
};
class A: public Visitable_impl_<A> {};
class B: public Visitable_impl_<B> {};
#include <iostream>
using namespace std;
auto main()
-> int
{
class Action
: public I_visitor
{
private:
void visit( A& ) override { cout << "Visited an A." << endl; }
};
I_visitable&& a = A();
I_visitable&& b = B();
Action x;
a.accept( x ); b.accept( x );
}
Now we just replace the first static_cast with a dynamic_cast, and voilà:
// Dynamic visitor pattern.
template< class Visitable >
class Visitor_
{
template< class > friend class Visitable_impl_;
private:
virtual void visit( Visitable& ) {}
};
struct I_visitor { virtual ~I_visitor(){} }; // Note: no mention of A or B.
class I_visitable
{
public:
virtual void accept( I_visitor& ) = 0;
};
template< class Visitable >
class Visitable_impl_
: public I_visitable
{
public:
void accept( I_visitor& v )
override
{
if( auto p_visitor = dynamic_cast<Visitor_<Visitable>*>( &v ) )
{
p_visitor->visit( static_cast<Visitable&>( *this ) ); // Cast for overload res.
}
}
};
class A: public Visitable_impl_<A> {};
class B: public Visitable_impl_<B> {};
#include <iostream>
using namespace std;
auto main()
-> int
{
class Action
: public I_visitor
, public Visitor_<A>
{
private:
void visit( A& ) override { cout << "Visited an A." << endl; }
};
I_visitable&& a = A();
I_visitable&& b = B();
Action x;
a.accept( x ); b.accept( x );
}

Related

Architecture of sub-classes in C++

I learn C++ OOP-paradigm and want to ask related question:
Assumption
We have a base class:
class Base {
public:
virtual SomeType PowerMethod() { return SomeType{} };
}
We have a variable target and subclass which realizes some calculations with target variable based on the constructor's parameter (simple calculations or complicated calcs):
class Calc : public Base {
public: // using only public access to simplify real code structure
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
Question
How to optimally realize two classes which based on different methods (Simple or Complex) but provide the same functionality of PowerMethod()?
My solution
class SimpleCalc : public Calc {
bool isSimple = true;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
class ComplexCalc : public Calc {
bool isSimple = false;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
This solution is pretty "ugly" and I want to ask you how to make it more readable.
Thank you!
I think that in your code, you didn't mean to craete a new Calc object, but instead call it on the superclass. This can be done like so:
Calc::Simple();
You can override the method PowerMethod, but still call the superclass's code:
virtual SomeType PowerMethod() override {
//do something
Base::PowerMethod();
}
If your problem is more complicated, and polymorphism and superclasses can't help you, you can always declare some method protected, so that only subclasses can access it. So, you could for example do this:
class Calc : public Base {
protected:
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
public:
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
class SimpleCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Simple();
return Calc::target;
};
};
class ComplexCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Complex();
return Calc::target;
};
};
If your target is to learn OOP then you can use a factory design pattern to create your final calculator based on isSimple condition:
#include <iostream>
class Base
{
public:
Base()
{
target = 0;
}
int target;
virtual void PowerMethod() = 0;
};
class SimpleCalc : public Base
{
virtual void PowerMethod() { target = 0; }
};
class ComplexCalc : public Base
{
virtual void PowerMethod() { target = 1000; }
};
class CalcFactory
{
public:
virtual Base* createCalc(bool isSimple)
{
if (isSimple)
return new SimpleCalc();
else
return new ComplexCalc();
}
};
int main()
{
CalcFactory factory;
Base * base1 = factory.createCalc(true);
Base * base2 = factory.createCalc(false);
base1->PowerMethod();
base2->PowerMethod();
std::cout << base1->target << std::endl;
std::cout << base2->target << std::endl;
}

Alternative approach to virtual template method

i am trying to solve this for some time and i hope to find some help here. I have a base class and inside the base class i need a template method. But this method can not be virtual (which i know) so i can not override it in the child class, but is there any alternative or workaround? Some kind of design pattern? Thanks
#include <iostream>
#include <vector>
#include <map>
class ABase {
public:
ABase() :
id(s_id++)
{}
size_t static s_id;
size_t id;
};
size_t ABase::s_id(0);
class A1 : public ABase {
public:
};
class A2 : public ABase {
public:
};
class BBase {
public:
};
class B1 : public BBase {
public:
};
class B2 : public BBase {
public:
};
class ComboBase {
public:
// this cannot be virtual :(
// so i cannot store b in bs in the child class
/* virtual */ template<typename T>
void addB(T b) {
}
};
template<class T, class T2>
class Combo : public ComboBase {
public:
// override of template method is not possible
/*
template<typename T>
void addB(T b) override {
bs.push_back(b);
}
*/
size_t id;
std::shared_ptr<T> a;
std::vector<std::shared_ptr<T2>> bs;
};
int main() {
std::map<size_t, std::shared_ptr<ComboBase>> combos;
auto combo1 = std::make_shared<Combo<A1, B1>>();
auto combo2 = std::make_shared<Combo<A2, B2>>();
combos[combo1->id] = combo1;
combos[combo2->id] = combo2;
// here is the problem... later i the code
// i would like to add Bs to the existing combo but i cannot use
// virtual templates
auto b1 = std::make_shared<B1>();
auto b2 = std::make_shared<B2>();
auto it1 = combos.find(0);
if (it1 != combos.end()) {
it1->second->addB(b1);
it1->second->addB(b2);
}
auto it2 = combos.find(0);
if (it2 != combos.end()) {
it2->second->addB(b1);
it2->second->addB(b2);
}
}

Best way to achieve late-stage polymorphism

I have several disparate templated pure abstract classes. I derive from these to get a bunch of classes, and from there, I can use those to make a bunch of objects. I would like to put all of these objects into a container. However, they are all of different types. I am wondering how to accomplish this late-stage polymorphism.
Say this is my pre-existing code that I have right now:
#include <iostream>
template<typename T>
class A{
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B{
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
A_example first;
B_example second;
first.printNum();
second.printTwiceNum();
return 0;
}
With more classes, it could get pretty messy inside of main(). Ideally I could jut iterate over the container and call print() on each element. My first thought is to use a std::vector<unique_ptr<Base>>. This seems to work:
#include <iostream>
#include <vector> // new include
#include <memory> // new include
#include <utility> // new include
// new Base class here
class Base{
public:
virtual ~Base(){};
};
template<typename T>
class A : public Base{ // new inheritance here
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B : public Base{ // new inheritance here as well
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
std::vector<std::unique_ptr<Base>> v;
v.emplace_back( new A_example() );
v.emplace_back( new B_example() );
//v[0]->printNum(); // nope
//v[1]->printTwiceNum(); // nope
return 0;
}
This is cool because I didn't have to change A_example or B_example, and all I changed in A and B was that I added : public Base. However, I have no idea how to call each elements print*** function. Is there any way to call the printNum() and printTwiceNum() functions, and for them to be automatically recognized?
The simplest approach is to just make a virtual function Base::print and have your derived classes implement it. But that's not always appropriate.
Another approach is to branch on dynamic_cast conversions. The premise there is that some functions are only available on some classes. But this can get hairy especially when using class templates, as you must handle all expected template parameters.
To generalize this, you can use interface classes. Let's say you have lots of different classes but only a small number of print variations. In that case, it may make sense to do this:
class PrintNumInterface {
public:
virtual void printNum() const = 0;
};
class PrintTwiceNumInterface {
public:
virtual void printTwiceNum() const = 0;
};
template<typename T> class A : public Base, public PrintNumInterface { ... };
template<typename T> class B : public Base, public PrintTwiceNumInterface { ... };
And now, no matter how many additional classes or template expansions you have to deal with, you only need to handle these interfaces:
for (auto& p : v)
{
if (PrintNumInterface* iface = dynamic_cast<PrintNumInterface*>(p.get())
iface->printNum();
else if (PrintTwiceNumInterface* iface = dynamic_cast<PrintTwiceNumInterface*>(p.get())
iface->printTwiceNum();
}

C++ pure virtual method defined at run-time

Not sure if the name is very telling but here goes.
I am interfacing to an API that requires a base class to be inherited and a lot of pure virtual methods to be defined.
For good programming practice, I want these methods to be defined in different (sub) classes.
Currently, I use a facade/wrapper (kind of both) class, that inherits the base class, instantiates the sub-classes, and calls the necessary methods of these instantiated classes:
#include <cstdio>
class Base
{
public:
virtual void reqImplementation( void ) = 0;
};
class APIImplementation
{
private:
Base * ptr_;
public:
APIImplementation( Base * ptr ) :
ptr_( ptr )
{
ptr_->reqImplementation();
}
};
class MyImplementation
{
private:
APIImplementation * api_;
public:
void reqImplementation( void )
{
printf("Hello World!\n");
}
MyImplementation( APIImplementation * api ) : api_( api ) {}
};
class MyFacade : public Base
{
private:
MyImplementation * my_impl_;
APIImplementation * api_;
void reqImplementation( void )
{
my_impl_->reqImplementation();
}
public:
MyFacade( void )
{
api_ = new APIImplementation( this );
my_impl_ = new MyImplementation( api_ );
}
};
int main( void )
{
MyFacade my_facade;
return 0;
}
Is there any way to implement the pure virtual functions in the sub-classes instantiated within this facade/wrapper? Or, alternately, what would be good practice for something like this? I want something similar to this (I know it clearly doesn't work at the moment):
#include <cstdio>
class Base
{
public:
virtual void reqImplementation( void ) = 0;
};
class APIImplementation
{
private:
Base * ptr_;
public:
APIImplementation( Base * ptr ) :
ptr_( ptr )
{
ptr_->reqImplementation();
}
};
class MyImplementation : public Base
{
private:
APIImplementation * api_;
public:
void reqImplementation( void )
{
printf("Hello World!\n");
}
MyImplementation( APIImplementation * api ) : api_( api ) {}
};
class MyFacade : public Base
{
private:
MyImplementation * my_impl_;
APIImplementation * api_;
public:
MyFacade( void )
{
api_ = new APIImplementation( this );
my_impl_ = new MyImplementation( api_ );
}
};
int main( void )
{
MyFacade my_facade;
return 0;
}
Note the API source is open, so I can change these pure virtual methods to anything else, however the code is quite exhaustive, so I'd rather small changes than significant ones.
If I got you right, you need a virtual inheritance. Here's an example
#include <iostream>
using namespace std;
// base class with lots of methods (two, actually)
struct Base {
virtual void f() = 0;
virtual void g() = 0;
};
// here's a class with implementation of f
struct ImplementationPart1 : public virtual Base {
virtual void f() {
cout << 4;
}
};
// here's a class with implementation of g
struct ImplementationPart2 : public virtual Base {
virtual void g() {
cout << 2;
}
};
// here's a class with all the implementations
struct Implementation : public ImplementationPart1, public ImplementationPart2 {};
int main() {
// Implementation inherits from Base, yes
Base *x = new Implementation();
// everything works, as expected
x->f();
x->g();
}
Live example.

Right design pattern to deal with polymorphic collections of objects

Suppose I have the following classes:
class BaseObject {
public:
virtual int getSomeCommonProperty();
};
class Object1: public BaseObject {
public:
virtual int getSomeCommonProperty(); // optional
int getSomeSpecificProperty();
};
class BaseCollection {
public:
virtual void someCommonTask();
};
class Collection1: public BaseCollection {
public:
virtual void someCommonTask(); // optional
void someSpecificTask();
};
Each collection, derived from BaseCollection, deals with a specific object type (and only one type). But BaseCollection should be able to perform some tasks that are common to all objects, using only common object properties in BaseObject.
Currently, I have potentially three solutions in mind:
1) Store the objects list in BaseCollection, such as:
class BaseCollection {
vector<BaseObject*> objects;
};
The problem with this solution is that when I need to perform object-specific task in Collection1, I need a dynamic_cast<>, because I don't want to use virtual inherance for specific properties, applying to only one type of object. Considering that dynamic_cast<> could potentially get called millions of time per second, this seems an issue for a performance critical application.
2) Store the objects list in Collection1, such as:
class Collection1: public BaseCollection {
vector<Object1*> objects;
}
But then I need some way to access this object list in BaseCollection, to be able to perform some common tasks on them, ideally through an iterator. I would need to create a function that return a vector for the BaseCollection, but again, this does not seem very efficient, because the only way to do that is to create a new vector (potentially containing thousands of objects)...
3) Store the objects list in BaseCollection AND Collection1:
class BaseCollection {
public:
void someCommonTask(); // Use baseObjects
virtual void addObject() = 0;
protected:
vector<BaseObject*> baseObjects;
};
class Collection1: public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
}
Where the two lists actually contain the same objects. Is that as ugly as it sounds like?
I am looking for the right/correct/best design pattern for this type of problem and none of the 3 solutions exposed above really satisfies me...
Maybe it is possible to solve that problem with templates, but then I don't see a way to store a list of polymorphic collections like this:
vector<BaseCollection*> collections;
You can store all your objects of base and derived classes in one collection through the base class (smart) pointer. Using visitor design pattern and double dispatch mechanism you can call a function only on objects of a specific type without having to expose that function in the base class interface. For example:
#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <stdio.h>
struct Visitor { // Visitor design patter
virtual void visit(struct BaseObject&) {}
virtual void visit(struct Object1&) {}
};
struct BaseObject {
unsigned ref_count_; // intrusive_ptr support
BaseObject() : ref_count_() {}
virtual ~BaseObject() {}
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
void intrusive_ptr_add_ref(BaseObject* p) { // intrusive_ptr support
++p->ref_count_;
}
void intrusive_ptr_release(BaseObject* p) { // intrusive_ptr support
if(!--p->ref_count_)
delete p;
}
struct Object1 : BaseObject {
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
void getSomeSpecificProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class T, class Functor>
struct FunctorVisitor : Visitor {
Functor f_;
FunctorVisitor(Functor f) : f_(f) {}
void visit(T& t) { f_(t); } // apply to T objects only
template<class P> void operator()(P const& p) { p->accept(*this); }
};
template<class T, class Functor>
FunctorVisitor<T, Functor> apply_to(Functor f)
{
return FunctorVisitor<T, Functor>(f);
}
int main()
{
typedef boost::intrusive_ptr<BaseObject> BaseObjectPtr;
typedef std::vector<BaseObjectPtr> Objects;
Objects objects;
objects.push_back(BaseObjectPtr(new BaseObject));
objects.push_back(BaseObjectPtr(new Object1));
for_each(
objects.begin()
, objects.end()
, boost::bind(&BaseObject::getSomeCommonProperty, _1)
);
for_each(
objects.begin()
, objects.end()
, apply_to<BaseObject>(boost::bind(&BaseObject::getSomeCommonProperty, _1))
);
for_each(
objects.begin()
, objects.end()
, apply_to<Object1>(boost::bind(&Object1::getSomeSpecificProperty, _1))
);
}
Output:
$ ./test
virtual void BaseObject::getSomeCommonProperty()
virtual void Object1::getSomeCommonProperty()
virtual void BaseObject::getSomeCommonProperty()
void Object1::getSomeSpecificProperty()
I think you should go for option 1 but use a static cast instead. After all the derived collection knows the type of the member variable for sure.
This answer explains it very well.
Id use nested adapter as in below example. You have to specialize it for every class you want to do a fancy update
!The example has memory leak - allocated A, B, Q objects are not deleted!
#include <iostream>
#include <vector>
#include <algorithm>
class Q
{
public:
virtual void Foo()
{
std::cout << "Q::Foo()" << std::endl;
}
};
class A
{
public:
virtual void Foo()
{
std::cout << "A::Foo()" << std::endl;
}
};
class B : public A
{
public:
virtual void Foo()
{
std::cout << "B::Foo()" << std::endl;
}
virtual void BFoo()
{
std::cout << "B::BFoo()" << std::endl;
}
};
template <typename ElementType>
class C
{
public:
template <typename T>
void add(T* ptr){m_Collection.push_back(std::unique_ptr<Adapter>(new ConcreteAdapter<T>(ptr)));}
void updateAll()
{
std::for_each(m_Collection.begin(), m_Collection.end(), [&](std::unique_ptr<Adapter> &adapter)->void{adapter->update();});
}
private:
class Adapter
{
public:
virtual ElementType* get() = 0;
virtual void update(){get()->Foo();}
};
template <typename T>
class ConcreteAdapter : public Adapter
{
public:
ConcreteAdapter(T* ptr) : m_Ptr(ptr){}
virtual T* get(){return m_Ptr;}
protected:
T* m_Ptr;
};
template <>
class ConcreteAdapter<B> : public Adapter
{
public:
ConcreteAdapter(B* ptr) : m_Ptr(ptr){}
virtual B* get(){return m_Ptr;}
virtual void update()
{
get()->Foo();
get()->BFoo();
}
private:
B* m_Ptr;
};
std::vector<std::unique_ptr<Adapter>> m_Collection;
};
int main()
{
C<A> c;
c.add(new A());
c.add(new B());
//c.add(new Q()); //error - correct
c.updateAll();
return 0;
}
Maybe this will do the trick here ?
class CollectionManipulator {
public:
void someCommonTask(BaseCollection& coll) {
for(unsigned int i = 0; i < coll.size(); i++)
someCommonTask(coll.getObj(i));
}
private:
void someCommonTask(BaseObject*); // Use baseObjects
};
class BaseCollection {
friend class CollectionManipulator;
private:
virtual BaseObject* getObj(unsigned int) = 0;
virtual unsigned int size() const = 0;
};
class Collection1 : public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
private:
BaseObject* getObj(unsigned int value) {
return object[value];
}
unsigned int size() const {
return objects.size();
}
}
If you want abstract your container in Collection1 (like using list instead using vector), to use it in Manipulator, create an abstract iterator...
I think the solution should be a mix of factory method pattern and template method pattern. Take a look at those to refine your design.
Edit: Here is a sample code. GenericProduct is the BaseObject, it provides two methods, one that is general (though it could be overridden), and a specific method which does nothing, it is not a pure virtual so this class can be instantiated. SpecificProduct is a subclass, which implements the specific method in some way.
Now, Factory class is an abstract class that defines an interface for creating specific products by specific factories, it defines a pure virtual method createProduct which creates the product. Two concrete factories are created GenericFactory and SpecificFactory which create specific products.
Finally, the Consumer abstract class (which corresponds to BaseCollection in your code), it defines a pure virtual method for creating a factory createFactory in order to force subclasses to create their own concrete factories (and hence, the correct products). The class also define a method fillArray (prototype pattern) to fill the array with products created by the factory.
#include <iostream>
#include <vector>
using namespace std;
class GenericProduct{
public:
virtual void getSomeCommonProperty()
{
cout<<"Common Property\n";
}
virtual void getSomeSpecificProperty()
{
cout<<"Generic Has Nothing Specific\n";
}
};
class SpecificProduct : public GenericProduct{
public:
virtual void getSomeSpecificProperty()
{
cout<<"Specific Product Has a Specific Property\n";
}
};
class Factory
{
public:
virtual GenericProduct* createProduct() = 0;
};
class GenericFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new GenericProduct();
}
};
class SpecificFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new SpecificProduct();
}
};
class Consumer
{
protected:
vector<GenericProduct*> gp;
Factory* factory;
protected:
virtual void createFactory() = 0;
public:
void fillArray()
{
createFactory();
for(int i=0; i<10; i++)
{
gp.push_back(factory->createProduct());
}
}
virtual void someCommonTask()
{
cout<<"Performaing a Common Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeCommonProperty();
}
}
virtual void someSpecificTask()
{
cout<<"Performaing a Specific Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeSpecificProperty();
}
}
};
class GenericConsumer : public Consumer
{
virtual void createFactory()
{
factory = new GenericFactory();
}
};
class SpecificConsumer : public Consumer
{
virtual void createFactory()
{
factory = new SpecificFactory();
}
};
int main()
{
Consumer* c = new GenericConsumer();
c->fillArray();
c->someCommonTask();
return 0;
}