2011-08-23 44 views
7

JavaScript novato aquí, yo estaba pasando por algo de código js en el trabajo cuando me encontré con una función de ayuda para la creación de objetos, que fue como estocreación de objetos 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... > 
} 

mientras que esto no hacer el trabajo lo haría desea saber si hay una forma mejor y más limpia de escribir esto.

+0

Usted puede estar interesado en la [estructura de conmutación] (https://developer.mozilla.org/en/JavaScript/Reference/Statements/switch) ... – DaveRandom

Respuesta

9

Tienes razón, la if..then o switch lógica es code smell y casi siempre se puede refactorizar en algo más elegante. En este caso, una fábrica en base a un nombre puede ser reprogramado para utilizar un diccionario con la clave como el nombre y el valor que la función para devolver

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); 
} 

ejemplo vivo: http://jsfiddle.net/KkMnd/

EDIT: esa línea en el método createElement podría/debería verificar primero que algo esté configurado para el TYPES.* pasado. Una buena forma es verificar que haya un elemento en el diccionario antes de intentar llamar a ese método.

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

me gusta su respuesta mejor. – Prospero

+0

+1 Y lo bueno de esta solución es que si necesita 'expandir' TYPES', no tiene que cambiar ninguna * lógica * para hacerlo, lo que tendría que hacer con un 'switch'. – peirix

+3

+1 para simplificar y mencionar el nombre de este patrón (un patrón de fábrica). Lo que me preocupa es que OP no mencionó la última declaración "_else_" y usted debería implementarla aquí también, por ej. 'return (typeof dictionary [name]! = 'undefined')? diccionario [nombre] (datos): something_goes_here; '(simplemente reemplace' something_goes_here' con el resultado esperado si no encuentra nada). – Tadeck

0

Sería un poco más limpio, pero semánticamente lo mismo para usar una declaración de interruptor.

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 
} 
}