Usando il mouse come un multi-strumento si crea una pesante logica condizionale per l'esecuzione di comandi, come posso cambiarlo?

4

La funzione si trova in molti diversi tipi di programmi di editing in cui un clic del mouse può avere comandi completamente diversi da eseguire (usando il Command Pattern)

Attualmente ho una funzione determineClickCommand(clickFocus) dominante. Il corpo sembrava essenzialmente questo:

var command = null;
var args    = null;

if (clickFocus == x) {
    if (x.state == state) {
        args = // Code to detemine args
        command = new CommandA(args)
    } else {
        command = new CommandB()
    }
} else if (clickFocus == y) {
    args = blahablah;
    command = new CommandC(args)
} else if (clickFocus == z) {
    command = new CommandD()
} ...etc..etc...etc...

command.execute()

Che andava bene quando stavo prototipando, ma mi piacerebbe una soluzione più elegante. In particolare da quando, a un certo punto, voglio sfruttare il tasto destro del mouse / il tasto centrale del mouse, che potrebbe aggiungere una terza istruzione if annidata

La mia prima idea è quella di creare una classe AbstractClickScope con un metodo determineClickCommand() da sovrascrivere in ciascuna sottoclasse concreta di ambito. Questo rompe il problema in classi più manutenibili, ma l'ampia logica condizionale è la stessa identica. E se dovessi decidere di avere molti 'ambiti' allora una nuova lezione ogni volta sarebbe molto fastidiosa.

O forse hai una sorta di classe factory di comando rispetto a un metodo? Questo isola la creazione del comando in una parte molto specifica del codice.

Qualche altra idea? O implementazioni conosciute? Basta lanciare idee là fuori e cercare ulteriori informazioni come penso attraverso questo.

    
posta Cyril Silverman 27.02.2013 - 01:48
fonte

3 risposte

1

Stai cercando un modo per eliminare un po 'di codice gonfiato e semplificare la tua interfaccia, il che è fantastico. Il mio suggerimento è, invece di utilizzare if/else istruzioni o switch/case blocchi, utilizzare qualcosa di più gestibile come un dizionario / hashmap.

Ecco l'idea generale dell'utilizzo di un hash di ricerca. (Questo è pseudocodice, quindi scusate eventuali discrepanze di sintassi e blocchi di codice omessi.) Supponiamo di avere le seguenti classi:

class A {
    method1 () {}
    method2 () {}
}

class B {
    method3 () {}
    method4 () {}
}

Invece di dire questo:

if (clickFocus == x) {
    if (x.state == state) {
        // execute A.method1
    } else {
        // execute A.method2
    }
} else if (clickFocus == y) {
    // execute B.method3
} else if (clickFocus == z) {
    // execute B.method4
} ...etc..etc...etc...

... potresti memorizzare queste chiamate in una hashmap con coppie chiave / valore, ad esempio:

class MouseHandler {
    public myHashMap = new Hashmap;
    myHashMap.x = A.method1; // Reference (or pointer) to function
    myHashMap.y = A.method2; // or possibly function body itself
    myHashMap.z = B.method3;
}

Quindi, puoi semplicemente passare il tuo clickFocus sulla mappa come parametro, che restituirà la funzione che desideri. Quindi avresti qualcosa di simile:

function getCommandForMouseEvent(clickFocus) { // return a function reference
    return MouseHandler.myHashMap[clickFocus];
}

Si noti che questo è veramente semplificato, ma fare qualcosa del genere dovrebbe ridurre un po 'il codice. (Questo potrebbe effettivamente corrispondere a uno dei modelli di progettazione che hai citato. Ho davvero bisogno di leggerli.) L'altra cosa bella di questo è che puoi aggiungere chiavi al tuo hash durante il runtime, così puoi registrare nuove funzionalità.

Spero che abbia un senso, e spero che serva da buon punto di partenza.

    
risposta data 27.02.2013 - 04:24
fonte
1

Questo è uno dei lavori che i framework dell'interfaccia utente grafica fanno per te. Un tipico framework GUI impiegherà una gerarchia di viste e un modo per trovare la vista particolare per una determinata coordinata. Quando il mouse fa qualcosa (muove, abbottona, abbottona, ecc.), La struttura trova la vista pertinente e invia un messaggio appropriato, come "il tasto sinistro del mouse è sceso alle coordinate locali (127, 225)". Spetta quindi alla vista decidere cosa fare con tali informazioni e ciascuna vista è libera di prendere qualsiasi azione sia necessaria. Ad esempio, un pulsante potrebbe ignorare le coordinate e ridisegnarsi da solo in uno stato selezionato, mentre una visualizzazione di testo potrebbe spostare il punto di inserimento.

Se stai lavorando con un framework GUI, non dovresti preoccuparti troppo di trattare direttamente con il mouse. Scopri come funziona il tuo framework e utilizza questo meccanismo. Se stai cercando di scrivere il tuo framework, sarebbe probabilmente una buona idea esaminare due o tre framework esistenti e scoprire come funzionano - scoprirai che c'è molta comunanza, e probabilmente vuoi che il tuo framework faccia all'incirca la stessa cosa.

    
risposta data 27.02.2013 - 05:52
fonte
0

Potresti utilizzare lo modello di progettazione dello stato per questo. Sembra che tu abbia una situazione diversa per ogni valore di clickFocus , quindi potresti inserire il codice per gestire il clic su quegli oggetti. Ciò rimuove l'enorme catena di casi if-else nel metodo.

    
risposta data 27.02.2013 - 08:21
fonte

Leggi altre domande sui tag