I am trying to write an object "template" that use pImpl and MVC pattern to encapsulate everything not specific to the object. The following is how I tried to attempt it. I am sure that the code smells (if not stinks) but can't tell what's wrong with the design.
I would like to know what better alternatives with which I can do this.
#include <iostream>
using namespace std;
class Ancestor{}; //every object using the "template" inherits this class
//use a template as the type of IMPL is only known at compile time
template <typename IMPL> class Obj : public Ancestor {
public:
//dependency injection for easy TDD
Obj(IMPL *impl = new IMPL()) : m_pImpl(impl) {};
~Obj() {delete m_pImpl; m_pImpl = nullptr;};
protected:
IMPL *m_pImpl;
};
// well a template is used for the same reason as for Obj<>
template <typename MODEL> struct MVCController {
MODEL *m_pModel;
};
// same reason for a template
template <typename MODEL, typename CONTROLLER> struct MVCImpl {
MODEL *m_pModel;
CONTROLLER *m_pController;
// leave alone the View for simplicity
//constructor
MVCImpl(MODEL *m = new MODEL(), CONTROLLER *c = new CONTROLLER()) :
m_pModel(m), m_pController(c) {m_pController->m_pModel = m;};
};
struct someBaseModel{};
If I want to create an object called myObj
with a public API void foo()
:
struct myModel : someBaseModel {
// POD
};
struct myController : public MVCController<myModel> {
void foo() {cout << "myController: foo" << endl;};
};
struct myImpl : public MVCImpl<myModel, myController> {};
class myObj : public Obj<myImpl> {
public:
// inherit myBaseObj to call its default ctor/dtor if no customization is needed
myObj(myImpl *impl = new myImpl()) : Obj<myImpl>(impl) {};
void foo();
};
void myObj::foo() {m_pImpl->m_pController->foo();};
If I want myDerivedObj
to inherit myObj
and add a void bar()
:
struct myDerivedController : public myController {
void bar() {cout<<"myDerivedController: bar"<<endl;};
};
struct myDerivedImpl : public MVCImpl<myModel, myDerivedController> {};
// virtual inheritance is used as both inherited class inherits from Ancestor
class myDerivedObj : virtual public myObj, virtual public Obj<myDerivedImpl> {
using Obj<myDerivedImpl>::m_pImpl;
public:
myDerivedObj(myDerivedImpl *impl = new myDerivedImpl()) :
Obj<myDerivedImpl>(impl) {};
// add any new API here
void bar();
};
void myDerivedObj::bar() {m_pImpl->m_pController->bar();};
int main() {
auto m2 = new myDerivedObj();
m2->foo();
m2->bar();
return 0;
}
Output:
myController: foo myDerivedController: bar
By using the above implementation I am trying to
- hide all pImpl and MVC specific code in the templates
- hide all generic "object behaviors" in Ancestor
- leave the possibility for inheritance
myDerivedObj
,foo
, andbar
aren't suitable for review. – 200_success♦ Aug 28 '14 at 8:51