It looks something like this.
Pusher classes => __raw data__ => DataManager => __processed data__ => listener classes
So far so good. The left half of this graph seems to be easy to structure, as the DataManager simply provides a few public functions to push different kinds of data, and those are the calls made from the pusher classes. Even though those functions have different signatures for different types of data, there's only one place of access, namely the manager itself.
The right side of the graph is a bit more problematic. That's because every listener listens to different types of data. Thus the function signatures of the listeners have to reflect the signatures of the corresponding DataManager functions, creating a dependency, and a maintenance nightmare.
So my code currently looks like this.
ZDataManager
{
//heterogeneous listener registration / unregistration
void RegisterFruitListener(ZFruitListener*);
void RegisterVegetableListener(ZVegetableListener*);
void RegisterBerryListener(ZBerryListener*);
//...plus corresponding unregistration functions
//heterogeneous receiver functions for receiving different types of data
void ReceiveNewFruit(ETexture, EColor, ETaste);
void ReceiveNewVegetable(string sVeggieName, float fVeggieWeight);
void ReceiveNewBerry(float fYumminessFactor, float fVitaminsPerGram);
//multiple arrays of heterogeneous listeners
list<ZFruitListener
list<ZVegetableListener
list<ZBerryListener
}
void ZDataManager::ReceiveNewFruit(ETexture eText, EColor eCol, ETaste eTaste)
{
list<ZFruitListener*>
while (en.MoveNext())
{
en.Current()->NewFruitReceived(eText, eCol, eTaste);
}
}
//...here we have almost identical definitions for ReceiveNewVegetable and ReceiveNewBerry, but with different function signatures!!
Then we have the listener classes, doing the following:
ZFruitListener::Init() {
GetDataManager()->RegisterFruitListener(this);
}
ZFruitListener::~ZFruitListener() {
GetDataManager().UnregisterFruitListener(this);
}
ZFruitListener::NewFruitReceived(ETexture, EColor, ETaste)
{
//process new fruit
}
//same idea for ZVegetableListener / ZFruitListener Init, destructor, and receiving functions.
As you can see here, I'm writing a lot of duplicate code, maintaining similar lists, registering classes in a similar way, and multicasting to different functions, but in a similar way. The main stumbling block here is the fact that the function signatures are different, making a more smooth solution elusive.
I posted a possible solution here:
ReplyDeletehttp://mortensjapan.blogspot.com/2010/11/coding.html
Phew you went all out :) I'll have a look thru soon, and will post my own solution, which is going in a slightly different direction.
ReplyDelete