2011-08-23 21 views
7

JavaScript newbie qui, stavo passando un certo codice js al lavoro quando mi sono imbattuto in una funzione di supporto per la creazione di oggetti, che è andato come questocreazione di oggetti JavaScript

createElement = function(name, data){ 
    if(name == TYPES.TEXT){ 
    return new Text(data); 
    } 
    else if(name == TYPES.WORD){ 
    return new Word(data); 
    } 
    else if(name == TYPES.PARAGRAPH){ 
    return new Paragraph(data); 
    } 
    else if(name == TYPES.TABLE){ 
    return new Table(data); 
    } 
    <list goes on and on and on... > 
} 

mentre questo non ottenere il lavoro fatto lo farei piacerebbe sapere se c'è un modo migliore e più pulito di scrivere questo.

+0

Potresti essere interessato al [struttura switch] (https://developer.mozilla.org/en/JavaScript/Reference/Statements/switch) ... – DaveRandom

risposta

9

Hai ragione, la if..then eccessiva o la switch logica è una code smell e può quasi sempre essere refactored in qualcosa di più elegante. In questo caso, una fabbrica basata su un nome può essere riscritta in un dizionario con chiave come quel nome e valore come la funzione per restituire

var dictionary = {}; 
dictionary[TYPES.TEXT] = Text; 
dictionary[TYPES.WORD] = Word; 
dictionary[TYPES.PARAGRAPH] = Paragraph; 
dictionary[TYPES.TABLE] = Table; 

createElement = function(name, data){ 
    return new dictionary[name](data); 
} 

esempio dal vivo: http://jsfiddle.net/KkMnd/

EDIT: Quella linea in il metodo createElement potrebbe/dovrebbe prima verificare che qualcosa sia stato configurato per il TYPES.* passato. Un buon modo è controllare che ci sia un elemento nel dizionario prima di provare a chiamare quel metodo.

return (typeof dictionary[name] == 'function') ? new dictionary[name](data) : some_default_value; 
+0

Mi piace la sua risposta migliore. – Prospero

+0

+1 E la cosa più interessante di questa soluzione è che se il tuo 'TYPES' deve essere espanso, non devi modificare alcuna * logic * per farlo, cosa che dovresti fare con un' switch'. – peirix

+3

+1 per semplificare e menzionare il nome di questo modello (un modello di fabbrica). Ciò che mi preoccupa è che OP non ha menzionato l'ultima frase "_else_" e dovresti implementarla anche qui, ad es. 'return (typeof dictionary [nome]! = 'undefined')? dizionario [nome] (dati): something_goes_here; '(sostituisci' something_goes_here' con il risultato atteso se non trovi nulla). – Tadeck

0

Sarebbe un po 'più pulito ma semanticamente lo stesso per utilizzare una dichiarazione di commutazione.

function createElement(name,data){ 
switch(name) 
{ 
case TYPES.TEXT: 
    return new Text(data) 
    break; 
case TYPES.WORD: 
    return new WORD(data) 
    break; 
default: 
    // etc. code to be executed if no values match 
} 
} 
Problemi correlati