M
ManicQin
Hello everyone and especially Kai-Uwe Bux
A month ago I post a question in the same name of this one but I didnt
managed to explain my question right, so people didn't understand me.
Now when I have the time to post it again I hope I could manage to
explain my self + to post the answer to my previous question.
So...
When you look at the Composite GOF pattern it's basically
//Snip
class Interface
{
virtual void work() = 0;
}
class compositor : public Interface
{
void work()
{ //Iterate through all the instances that the
//Class holds and call their work function
}
void addItem(Interface* newItem)
{ //you get the point }
vector<Interface*> m_Items
};
class workerA : public Interface {}
class workerB : public Interface {}
//Snip
If you want to add a new different class that inherits from a new
different Interface you will need to Copy Paste a new compositor.
If you want to Generalize the compositor you are heading to the
problem of how to keep it strong typed.
You can always use a master Object that all object are descendants of
him but you
will loose the strong type characteristic.
You can create a all purpose compositor but than you loose the
polymorphism of the classes
(If your interface "working" function is go() and your compositor
"working" function is Iterate() you cannot use a pointer to the
interface to handle a compositor (thus loosing the point))
OK so I patched up a Strong Typed Generic Compositor I added the code
at the end
(BTW works on VS2008 Express but not on VS6)
My new problem is how to further generalize the function call,
I have two solutions
1) To add a template for each possible function
A template for a function that returns void and 1 arg
A template for a function that -""- -""- and 2 args
and so one .. I've seen it many time but I dislike this solution
2) To add another level of abstraction and to patch up
classes for retVals and argVals (a bit of meta programming)
What do you think is better
//snip
#include <iostream>
#include <vector>
using namespace std;
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
class IWorker
{
public:
virtual void work() = 0;
};
class ILaborer
{
public:
virtual void labor() = 0;
};
template <class T,void (T::*funcPtr)()>
class ABCCompositor
{
public:
typedef vector<T*> tItemVec;
void addItem(T* newItem)
{
m_ItemCol.push_back(newItem);
}
void IterateThrough()
{
for (tItemVec::iterator iDx = m_ItemCol.begin();
iDx < m_ItemCol.end(); iDx++)
{
CALL_MEMBER_FN(*(*iDx),funcPtr)();
}
}
protected:
tItemVec m_ItemCol;
};
class WorkerCompositor : public IWorker,
public ABCCompositor<IWorker,&IWorker::work>
{
public:
void work()
{
IterateThrough();
}
};
class LaborerCompositor : public ILaborer,
public ABCCompositor<ILaborer,&ILaborer::labor>
{
public:
void labor()
{
IterateThrough();
}
};
class CPrinter : public IWorker
{
public:
void work()
{
cout << "Hello" << endl;
}
};
class CPrinter2 : public IWorker
{
public:
void work()
{
cout << " OLA!!!" << endl;
}
};
class CPrinter3 : public ILaborer
{
public:
void labor()
{
cout << "Shalom" << endl;
}
};
class CPrinter4 : public ILaborer
{
public:
void labor()
{
cout << "Salam" << endl;
}
};
int main()
{
WorkerCompositor printSession1;
WorkerCompositor printSession2;
printSession1.addItem(new CPrinter);
printSession1.addItem(new CPrinter2);
printSession1.addItem(new CPrinter);
printSession1.addItem(new CPrinter2);
printSession1.addItem(new CPrinter);
printSession2.addItem(&printSession1);
printSession2.addItem(new CPrinter2);
printSession2.work();
LaborerCompositor printSession3;
LaborerCompositor printSession4;
printSession3.addItem(new CPrinter3);
printSession3.addItem(new CPrinter4);
printSession3.addItem(new CPrinter3);
printSession3.addItem(new CPrinter4);
printSession3.addItem(new CPrinter3);
printSession4.addItem(&printSession3);
printSession4.addItem(new CPrinter3);
printSession4.labor();
return 0;
}
//snip
Thanks
A month ago I post a question in the same name of this one but I didnt
managed to explain my question right, so people didn't understand me.
Now when I have the time to post it again I hope I could manage to
explain my self + to post the answer to my previous question.
So...
When you look at the Composite GOF pattern it's basically
//Snip
class Interface
{
virtual void work() = 0;
}
class compositor : public Interface
{
void work()
{ //Iterate through all the instances that the
//Class holds and call their work function
}
void addItem(Interface* newItem)
{ //you get the point }
vector<Interface*> m_Items
};
class workerA : public Interface {}
class workerB : public Interface {}
//Snip
If you want to add a new different class that inherits from a new
different Interface you will need to Copy Paste a new compositor.
If you want to Generalize the compositor you are heading to the
problem of how to keep it strong typed.
You can always use a master Object that all object are descendants of
him but you
will loose the strong type characteristic.
You can create a all purpose compositor but than you loose the
polymorphism of the classes
(If your interface "working" function is go() and your compositor
"working" function is Iterate() you cannot use a pointer to the
interface to handle a compositor (thus loosing the point))
OK so I patched up a Strong Typed Generic Compositor I added the code
at the end
(BTW works on VS2008 Express but not on VS6)
My new problem is how to further generalize the function call,
I have two solutions
1) To add a template for each possible function
A template for a function that returns void and 1 arg
A template for a function that -""- -""- and 2 args
and so one .. I've seen it many time but I dislike this solution
2) To add another level of abstraction and to patch up
classes for retVals and argVals (a bit of meta programming)
What do you think is better
//snip
#include <iostream>
#include <vector>
using namespace std;
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
class IWorker
{
public:
virtual void work() = 0;
};
class ILaborer
{
public:
virtual void labor() = 0;
};
template <class T,void (T::*funcPtr)()>
class ABCCompositor
{
public:
typedef vector<T*> tItemVec;
void addItem(T* newItem)
{
m_ItemCol.push_back(newItem);
}
void IterateThrough()
{
for (tItemVec::iterator iDx = m_ItemCol.begin();
iDx < m_ItemCol.end(); iDx++)
{
CALL_MEMBER_FN(*(*iDx),funcPtr)();
}
}
protected:
tItemVec m_ItemCol;
};
class WorkerCompositor : public IWorker,
public ABCCompositor<IWorker,&IWorker::work>
{
public:
void work()
{
IterateThrough();
}
};
class LaborerCompositor : public ILaborer,
public ABCCompositor<ILaborer,&ILaborer::labor>
{
public:
void labor()
{
IterateThrough();
}
};
class CPrinter : public IWorker
{
public:
void work()
{
cout << "Hello" << endl;
}
};
class CPrinter2 : public IWorker
{
public:
void work()
{
cout << " OLA!!!" << endl;
}
};
class CPrinter3 : public ILaborer
{
public:
void labor()
{
cout << "Shalom" << endl;
}
};
class CPrinter4 : public ILaborer
{
public:
void labor()
{
cout << "Salam" << endl;
}
};
int main()
{
WorkerCompositor printSession1;
WorkerCompositor printSession2;
printSession1.addItem(new CPrinter);
printSession1.addItem(new CPrinter2);
printSession1.addItem(new CPrinter);
printSession1.addItem(new CPrinter2);
printSession1.addItem(new CPrinter);
printSession2.addItem(&printSession1);
printSession2.addItem(new CPrinter2);
printSession2.work();
LaborerCompositor printSession3;
LaborerCompositor printSession4;
printSession3.addItem(new CPrinter3);
printSession3.addItem(new CPrinter4);
printSession3.addItem(new CPrinter3);
printSession3.addItem(new CPrinter4);
printSession3.addItem(new CPrinter3);
printSession4.addItem(&printSession3);
printSession4.addItem(new CPrinter3);
printSession4.labor();
return 0;
}
//snip
Thanks