2012-05-15 10 views
11

Sono di fronte al seguente enigma: il nostro software ha una classe base astratta per gli oggetti algoritmici. Tutti questi oggetti hanno un metodo comune execute(), ad es .:Parametri generici (quasi) auto-descrittivi in ​​C++ accoppiato con una GUI?

class Algorithm 
{ 
public: 
    // [...] 
    virtual void execute() = 0; 
    // [...] 
}; 

Per ogni algoritmo che vogliamo implementare, abbiamo semplicemente ereditare dalla classe base e memorizzare tutti gli oggetti caricati algoritmo in una posizione centrale. Fin qui tutto bene.

Il problema ora risiede nei parametri di un algoritmo. Vogliamo essere in grado di descrivere per ogni algoritmo i parametri che devono essere impostati (da una classe esterna). A tal fine, abbiamo assegnato ad ogni algoritmo un oggetto ParameterList che contiene i suoi parametri. Devo chiarire che, per noi, un parametro è costituito da un certo tipo di tipo (come ad esempio int) e un'etichetta (come "numero di iterazioni).

Il problema ora inizia quando vogliamo collegare il ParameterList ad un certo genere della GUI Ovviamente, i nostri algoritmi non dovrebbero avere alcuna "conoscenza" dell'API grafica (Qt, GTK, ecc.) che stiamo usando, tuttavia, dalla stessa parte, vogliamo essere in grado di descrivere semanticamente i parametri degli algoritmi, ad esempio specificando che l'algoritmo richiede un nome di file . Come viene quindi visualizzato questo nome spetta alla GUI.

esiste un modo per combinare questo ParameterList con qualche tipo di conoscenza di tipo semantico?

Mi rendo conto che questa domanda sembra molto vaga. Tuttavia, non sono autorizzato a pubblicare esempi di codice non banali (per ragioni NDA). Quindi, qualcuno ha dovuto affrontare un problema simile in passato?

Per riassociare: Vogliamo che i nostri oggetti descrivano i parametri che richiedono a una GUI, senza conoscere i dettagli esatti della GUI.

+1

OK, guarda, * questa è * una buona domanda. E anche da un nuovo poster. C'è speranza, dopo tutto. –

+0

un altro metodo virtuale implementato in ogni classe di algoritmo che fornisce l'elenco dei parametri richiesti e le informazioni sul tipo (tale nome file -> quindi un campo di testo con un pulsante open-file, intero -> pulsante di rotazione ...) e così via ... la GUI chiede i parametri da mostrare per l'esecuzione di algo ... perché no? – ShinTakezou

risposta

9

Un'opzione potrebbe essere quella di utilizzare il modello di visitatore. È possibile creare una classe di base come questo:

class Parameter { 
public: 
    virtual ~Parameter() {} // Polymorphic classes need virtual dtors. 

    virtual void accept(ParameterVisitor& v) = 0; 
}; 

è possibile definire sottoclassi come questi:

class IntParameter: public Parameter { 
public: 
    virtual void accept(ParameterVisitor& v) { 
      v.visit(*this); 
    } 
}; 
class FilenameParameter: public Parameter { 
public: 
    virtual void accept(ParameterVisitor& v) { 
      v.visit(*this); 
    } 
}; 

Si noti che in ogni funzione accept membro, il tipo di *this è il tipo statico della classe - vale a dire, IntParameter& nel primo caso e FilenameParameter& nel secondo caso.

È quindi possibile definire una classe base ParameterVisitor classe come questa:

class ParameterVisitor { 
public: 
    virtual ~ParameterVisitor() {} // Polymorphic classes need virtual dtors. 

    virtual void visit(IntParameter& p) {} 
    virtual void visit(FilenameParameter& p) {} 
    /* .. etc. .. */ 
}; 

È quindi possibile creare una sottoclasse questo visitatore a tornare le informazioni sul tipo:

class Gui1ParameterVisitor: public ParameterVisitor { 
public: 
    virtual void visit(IntParameter& p) { 
     /* ... use GUI1 to create a field for an integer. */ 
    } 
    virtual void visit(FilenameParameter& p) { 
     /* ... use GUI1 to create a field for a filename. */ 
    } 
}; 

class Gui2ParameterVisitor: public ParameterVisitor { 
public: 
    virtual void visit(IntParameter& p) { 
     /* ... use GUI2 to create a field for an integer. */ 
    } 
    virtual void visit(FilenameParameter& p) { 
     /* ... use GUI2 to create a field for a filename. */ 
    } 
}; 

La classe ParameterList quindi possibile solo negozio una lista di Parameter* s. È quindi possibile creare la GUI istanziando il tipo di visitatore appropriato e quindi avere i suoi callback visit fare tutta la costruzione del widget. Questo finisce per essere sicuro per il tipo e recupera le informazioni che ti servono. Ha lo svantaggio che ogni volta che crei un nuovo tipo di parametro, devi aggiungere una nuova funzione membro visit alla classe ParameterVisitor, ma dovresti farlo comunque per fare tutta la costruzione della GUI.

Spero che questo aiuti!

+0

questo è interessante, ma non è complicato? Perché non una metainformazione molto semplice su ogni parametro, descrivendo il tipo possibile da cui la GUI estrae l'interfaccia necessaria? Una sorta di "ffi" per la GUI ... o simile – ShinTakezou

+1

Il problema con la metainformazione è che per trattare tutto genericamente, è necessario aggiungere un po 'di codice del modulo "se questo è un campo int, ecco come crea il widget, ecco come interpreti il ​​widget, ecc. " L'approccio sopra fa questo in un modo sicuro per il tipo che non richiede alcuna fusione. – templatetypedef

+0

ah, ovviamente mi manca la parte "feedback" che imposta il valore selezionato nella GUI per tornare all'oggetto. Ok, ora lo vedo :) – ShinTakezou