#ifndef GRAPH_H #define GRAPH_H ///////////////////////////////////////////////////////////////////////////// // graph.h - demonstrate Memento pattern with non-recursive // depth first search // // Jim Fawcett, CSE776 - Design Patterns, Summer 2003 #include ///////////////////////////////////////////////////////////////////////////// // class Node template class Node { public: Node(NodeVal v); NodeVal& value(); bool& marked(); Node* getUnmarkedChild(); void attachChild(Node* pNode); private: std::vector< Node* > _children; NodeVal _value; bool _visited; }; //----< initialize node with value and marking >----------------------- template Node::Node(NodeVal v) : _value(v), _visited(false) { } //----< return value type >-------------------------------------------- template NodeVal& Node::value() { return _value; } //----< get or set node marking >-------------------------------------- template bool& Node::marked() { return _visited; } //----< return an unmarked child pointer if any exist >---------------- template Node* Node::getUnmarkedChild() { vector< Node* >::iterator it; for(it=_children.begin(); it!=_children.end(); it++) { if((*it)->marked() == false) { return (*it); } } return NULL; } //----< attach a child node to this node >----------------------------- template void Node::attachChild(Node* pNode) { _children.push_back(pNode); } // /////////////////////////////////////////////////////////////////////// // class Caretaker template class Memento; template class Walker; // originator template class Caretaker { public: void acceptWalker(Walker *pWalk); void acceptMemento(); int returnMemento(); int numMementos() { return _mementos.size(); } private: Walker *_pWalk; std::vector< Memento* > _mementos; }; //----< register walker with Caretaker >------------------------------- template void Caretaker::acceptWalker(Walker *pWalk) { _pWalk = pWalk; } //----< pass memento to Caretaker for safekeeping >-------------------- template void Caretaker::acceptMemento() { Memento *pMem = _pWalk->CreateMemento(); _mementos.push_back(pMem); } //----< restore earlier state in Walker, destroy memento >------------- template int Caretaker::returnMemento() { if(_mementos.size() > 0) { Memento *pMem = _mementos.back(); _mementos.pop_back(); pMem->SetState(); delete pMem; } return _mementos.size(); } // ///////////////////////////////////////////////////////////////////////////// // class Walker template class Walker { friend class Memento; public: Walker(Node *start); void walk(); void SetMemento(Memento *m); Memento* CreateMemento(); private: Node *_currPos; Caretaker _ct; }; //----< initialize Walker with node, register with CareTaker >--------- template Walker::Walker(Node *start) : _currPos(start) { _ct.acceptWalker(this); } //----< non-recursive graph walk >------------------------------------- template void Walker::walk() { Node* pNode; do { _currPos->marked() = true; cout << "\n visiting node #" << (_currPos->value()); while((pNode = _currPos->getUnmarkedChild()) != 0) { _ct.acceptMemento(); _currPos = pNode; _currPos->marked() = true; cout << "\n visiting node #" << (_currPos->value()); } _ct.returnMemento(); } while(_ct.numMementos() > 0); } //----< pass current node to memento >--------------------------------- template void Walker::SetMemento(Memento *m) { m->GetState(); } //----< create a memento and initialize its state >-------------------- template Memento* Walker::CreateMemento() { Memento *pMem = new Memento(this); pMem->GetState(); return pMem; } // ///////////////////////////////////////////////////////////////////////////// // class Memento template class Memento { public: Memento(Walker *pWalker); void GetState(); void SetState(); private: Walker *_pWalker; Node *_pNode; }; //----< initialize Memento with Walker reference >--------------------- template Memento::Memento(Walker *pWalker) : _pWalker(pWalker) { } //----< Get Walker state and store it >-------------------------------- template void Memento::GetState() { _pNode = _pWalker->_currPos; } //----< Set Walker state from Memento store >-------------------------- template void Memento::SetState() { _pWalker->_currPos = _pNode; } #endif