Il modello di progettazione Composite menzionata da Sampson-chen era il modo giusto per un'implementazione che ho fatto per un piccolo monitor sviluppatori, consentendo di scegliere alcuni metodi di prova da una struttura di menu.
Ho una classe di base "Voce di menu" da cui derivano sottomenu e leafs (le voci di menu). Una foglia esegue semplicemente qualcosa, mentre un sottomenu apre un altro livello di menu.
Per esempio la classe di base potrebbe piacere simile a quello (quando si desidera utilizzare shared_pointers):
/*************************************************************//*!
* @brief The base class for all menu entry types (sub menus and sub menu entries/items)
******************************************************************/
class MenuEntry : public boost::enable_shared_from_this<MenuEntry>
{
public:
virtual ~MenuEntry(){}
/**************************************************************//*!
* @brief Default implementation to add menu entries; has to be re implemented
* @param[in] newSubMenuEntry - the new menu entry (another sub menu or leaf)
**************************************************************/
virtual void add(boost::shared_ptr<MenuEntry> newSubMenuEntry)=0;
/*****************************************************************//*!
* @brief Default implementation for call to menu entries; always returns false
* @return false - the function has not been re implemented
****************************************************************/
virtual bool call(void)
{
// the member function has not been re-implemented
return false;
}
/*****************************************************************************//*!
* @brief Default implementation, has to be reimplemented
* @return emptyVector - an empty vector
*********************************************************************************/
virtual std::vector<boost::shared_ptr<MenuEntry> > getChildren(void)
{
std::vector<boost::shared_ptr<MenuEntry> > emptyVector;
return emptyVector;
}
/*******************************************************************************//*!
* @brief Gives a pointer to the parent of the actual menu entry
* @return m_parent - pointer to the parent
******************************************************************************/
boost::shared_ptr<MenuEntry> parent(void)
{
return m_parent;
}
/***************************************************************************//*!
* @brief Default implementation for selecting a menu entry
* @param[in] desiredMenuEntry - the desired menu entry which shall be selected
* @return notExisting - a pointer to <b>this</b>
**********************************************************************************/
virtual boost::shared_ptr<MenuEntry> select(boost::shared_ptr<MenuEntry> desiredMenuEntry)=0;
/**************************************************************************//*!
* <B>Criticality: C0 \n\n</B>
* @brief Sets a pointer to the parent of new menu entry
* @param[in] pointerToParent - pointer to the parent
****************************************************************************/
void setParent(boost::shared_ptr<MenuEntry> pointerToParent)
{
m_parent = pointerToParent;
}
/***************************************************************************//*!
* @brief Default implementation for destroying children
*****************************************************************************/
virtual void destroy(void)=0;
protected:
/************************************************************************//*!
* @brief Constructor for a menu entry (sub menu or leaf)
* @param[in] menuEntryName - the name for the sub menu or leaf
*************************************************************************/
MenuEntry(std::string menuEntryName)
{
m_menuEntryName = menuEntryName;
}
};
Nel metodo di selezione a verificare tramite il valore di ritorno, se ho una foglia che esegue qualcosa, o un sottomenu, per il quale devo cambiare i miei suggerimenti.
Per comodità è possibile aggiungere metodi che trovano tutte le voci del menu secondario in un sottomenu per la visualizzazione, o metodi che consentono di creare una riga del titolo con il percorso del menu effettivo o simili ... Un'altra idea sarebbe metodi per scansione dell'albero dei menu per evitare doppie voci di menu asf.
Hai bisogno di una relazione ricorsiva. –
Usa un albero? Ogni nodo ha un'etichetta e può avere zero o più figli, generalizzabili a qualsiasi numero di menu nidificati. L'etichetta del nodo radice viene ignorata, vengono considerati solo i suoi figli. – Wug
@Seth Ho capito il tuo commento, ma non sono sicuro di come inserirlo nel codice – dchhetri