Рассмотрите сходства между каждым узлом графа, который вы описываете, и создайте для них класс (класс GraphElement ниже).Он должен инкапсулировать свои отношения с дочерними узлами и что-то делать локально с любыми входящими сообщениями (функция localAction).Затем вы должны получить классы, которые представляют конкретные варианты - например, упомянутый вами генератор изображений - и изменить локальное действие.Каждый класс может взять копию исходного сообщения или изменить его по своему усмотрению.
В моем примере кода здесь я создал узел графа по умолчанию - GraphNode - и заставил его просто печатать входящие сообщения перед передачей их дочерним узлам.Я использовал строковый объект для входящего сообщения - намного лучше, чем обычный старый массив C char * [пример: вы можете получить строку из char *, когда message2 создается в приведенном ниже коде].Я сделал эти ссылки на объекты const как дешевые, быстрые и никогда не изменяющие оригинал.
Я получил класс CatNode в качестве примера необходимой вам вариации.Объекты этого типа содержат историю всех сообщений и распечатывают эту историю при поступлении нового сообщения.Не очень полезный, но тем не менее хороший пример.Это демонстрирует, как каждый узел может сделать что-нибудь с копией исходного сообщения - переписать localAction ().Он также передает эту историю любым дочерним узлам - перезаписать входящие сообщения с изменением параметра, переданного в функцию deliveryMessage ().
#include <vector>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::vector;
using std::string;
class GraphNode
{
public:
GraphNode( string & name ) : mChildren(), mName(name) {}
GraphNode( const char * const name ) : mChildren(), mName(name==NULL?"":name) {}
virtual void incomingMessage( const string & str ) {
localAction(str); // This node is to do something.
deliverMessage(str); // Child nodes are to do things too.
}
void addChild( GraphNode * child ) {
mChildren.push_back( child );
}
protected:
// Rewrite this function for child classes who are to do different things with messages.
virtual void localAction( const string & str ) {
cout << mName << " : " << str << endl;
}
void deliverMessage( const string & str ) {
vector<GraphNode*>::iterator itr = mChildren.begin();
for( ; itr != mChildren.end(); ++itr )
(*itr)->incomingMessage(str);
}
// Data members
vector<GraphNode*> mChildren;
string mName;
}; // [ GraphNode ]
class CatNode : public GraphNode
{
public:
CatNode( string & name ) : GraphNode(name), mHistory() {}
CatNode( const char * const name ) : GraphNode(name), mHistory() {}
virtual void incomingMessage( const string & str ) {
localAction(str);
deliverMessage(mHistory);
}
protected:
virtual void localAction( const string & str ) {
mHistory += str;
cout << mName << " : " << mHistory << endl;
}
// Data members
string mHistory;
}; // [ CatNode ]
main()
{
// root -> childA
GraphNode root("Root Node");
CatNode childA("Child A");
root.addChild( &childA );
root.incomingMessage("Message1");
cout << endl;
// root -> childA -> childC
// \-> childB
GraphNode childB("Child B");
root.addChild( &childB );
GraphNode childC("Child C");
childA.addChild( &childC );
string message2("Message2");
root.incomingMessage(message2);
} // [ main ]