Re: multiple interfaces using template method pattern
I've been working on this and finally the lights are starting to turn
on for me (hope its not from an oncoming train). Sorry to burden
moderators and your eyeballs. I've extended and modified the
example. I've split the public classes from implementation classes
using the pimpl idiom. Public and pimpl classes form symmetical
hierarchies which are bridged together. I've thrown in a sample
StorageWidget subtype demonstrating how derivation works. I've
included the Updateable class which represents an interface the system
can use but end-users can't. Finally, there's the System class which
handles the internal framework tasks, such as updating all widgets
behind the scenes. I fell back to using friend classes, but in this
case its very controlled and symmetrical as they are only used to
allow the public class access to its single corresponding pimpl
class's private details(details the subtype pimples shouldn't have
access to and are thus private). This is looking promising for what I
need to do so far. Is anybody bored enough to peruse my design and
code below to poke some holes in in? Thanks a bunch.
Full app code:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
//tmp style updateable class
class Updateable
{
public:
void Update(){ return DoUpdate(); }
protected:
virtual void DoUpdate() = 0;
};
//hidden impl base class for a hierarchy of widget subtype impls
class WidgetImpl :
public Updateable//provides an update interface the system can use
but end users can't
{
public:
WidgetImpl(const string& name) : name_(name) {}
const string& getName(){ return name_; }
private:
virtual int DoProcess() = 0;
virtual bool DoIsDone() = 0;
private:
//provides a default implementation for DoUpdate (subtype can still
override)
virtual void DoUpdate(){ cout << "WidgetImpl(" << getName().c_str()
<< ")::DoUpdate" << endl; }
private:
//some fake example data
string name_;
bool isDoneProcessing_;
char* processBuffer_;
friend class Widget;
};
//tmp style public Widget base class for the widget heirarchy
class Widget
{
public:
//stable public interface
~Widget(){}
int Process(){ return pimpl_->DoProcess(); }
bool IsDone(){ return pimpl_->DoIsDone(); }
protected:
Widget(WidgetImpl* pimpl) : pimpl_(pimpl) {}//allows bridging the
pimpl
WidgetImpl* getPimpl(){ return pimpl_; }
private:
WidgetImpl* pimpl_;
};
//A concrete storable widget impl class
class StorageWidgetImpl : public WidgetImpl
{
public:
StorageWidgetImpl(const string& name) : WidgetImpl(name) {}
private://StorageWidgetImpl overrides with a provided default
implementation
virtual int DoStore(){ cout << "StorageWidgetImpl(" <<
getName().c_str() << ")::DoStore" << endl; return 1; }
virtual bool DoIsStored(){ cout << ":StorageWidgetImpl(" <<
getName().c_str() << ")::DoIsStored" << endl; return true; }
private://WidgetImpl overrides
virtual int DoProcess(){ cout << "StorageWidgetImpl(" <<
getName().c_str() << ")::DoProcess" << endl; return 1; }
virtual bool DoIsDone(){ cout << "StorageWidgetImpl(" <<
getName().c_str() << ")::IsDone" << endl; return true; }
private:
bool isStored_;
FILE* storageStream_;
friend class StorageWidget;
};
//tmp style public StorageWidget subtype
class StorageWidget : public Widget
{
public:
//stable public interface
StorageWidget(const string& name) : Widget(new
StorageWidgetImpl(name)) {}
StorageWidget(StorageWidgetImpl* pimpl):
Widget(dynamic_cast<WidgetImpl*>(pimpl)) {}//for further subtyping
int Store(){ return getPimpl()->DoStore(); }
bool IsStored(){ return getPimpl()->DoIsStored(); }
protected:
StorageWidgetImpl* getPimpl(){ return
static_cast<StorageWidgetImpl*>(Widget::getPimpl()); }
};
//some example framework/system/manager class
class System
{
public:
StorageWidget* CreateStorageWidget(const string& name)
{
StorageWidgetImpl* pimpl = new StorageWidgetImpl(name);
StorageWidget* widget = new StorageWidget(pimpl);
updateables_.push_back(pimpl);
return widget;
}
void Update()
{
for(vector<Updateable*>::iterator it = updateables_.begin(); it !=
updateables_.end(); ++it)
(*it)->Update();
}
private:
vector<Updateable*> updateables_;
};
void main()
{
System system;
StorageWidget* sw1 = system.CreateStorageWidget("sw1");
StorageWidget* sw2 = system.CreateStorageWidget("sw2");
system.Update();
sw1->IsDone();
sw1->Process();
sw2->IsDone();
sw2->Process();
sw1->IsStored();
sw1->Store();
sw2->IsStored();
sw2->Store();
system.Update();
getchar();
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]