Miniatura
1

Javascript: Patrones de diseño en la creación de objetos

Hace ya unos años, trabajé en Hotelopia, y allí el equipo de desarrollo tuvimos la opción de montar algunas formaciones sobre temáticas que íbamos necesitando. Una de esas ocasiones, decidimos que queríamos profundizar en javascript, y montamos un curso entero sobre el libro “Professional javascript for web developers” del gran Nicholas C. Zakas.

Últimamente, gran parte del código en que nos metemos es javascript, y en ocasiones cuando lees código (o lo creas) se te plantean dudas existenciales… es por ello que recordé uno de los temas de este libro, el de creación de objetos. Vamos a hablar un poco de algunos de los paradigmas y patrones que cuenta Zakas en su libro, pros y contras, etc…

Creando un objeto

var coche = new Object();
coche.marca = "Seat";
coche.modelo = "Ibiza";
coche.anyo = 2012;
coche.returnMarca = function(){
    alert(this.marca);
};

El problema es que crear muchos objetos con la misma interface duplicas mucho código.

Paradigma de Factoría

function crearCoche(marca, modelo, anyo){
    var o = new Object();
    o.marca = marca;
    o.modelo = modelo;
    o.anyo = anyo;
    o.returnMarca = function(){
        alert(this.marca);
    };
    return o;
}
var coche1 = crearCoche("Seat", "Ibiza", 2012);
var coche2 = crearCoche("Opel", "Astra", 2002);

Aquí solucionamos el problema de crear múltiples objetos, podemos llamarla muchas veces con diferentes argumentos, aún así, seguía el problema de la identificación de objetos (qué tipo de objeto es un objeto) y que la función returnMarca() se llamaba en todos los objetos, o sea que todos los objetos tendrían su propia versión de esa función…

Este problema se intentó resolver así:

function returnMarca(){
    alert(this.marca);
}
function crearCoche(marca, modelo, anyo){
    var o = new Object();
    o.marca = marca;
    o.modelo = modelo;
    o.anyo = anyo;
    o.returnMarca = returnMarca;
    return o;
}
var coche1 = crearCoche("Seat", "Ibiza", 2012);
var coche2 = crearCoche("Opel", "Astra", 2002);

No es otra cosa que sacar la función returnMarca fuera. Podríamos decir que “casi” se resuelve el problema, pero semánticamente aún queda cojo, porque la función no parece un método de un objeto.

Paradigma de Constructores

function CrearCoche(marca, modelo, anyo){
    this.marca = marca;
    this.modelo = modelo;
    this.anyo = anyo;
    this.returnMarca = function(){
        alert(this.marca);
    };
}
var coche1 = new CrearCoche("Seat", "Ibiza", 2012);
var coche2 = new CrearCoche("Opel", "Astra", 2002);

Aquí hay varios cambios, como el operador “new”, usamos this en lugar de crear un objeto, no usamos return… Lo creáis o no, aún tenemos el mismo problema.

Al igual que en la Factoría, los constructores duplican funciones y crean una copia diferente de la función para cada objeto.

Paradigma de Prototipos

function Coche(){}
Coche.prototype.marca = "Opel";
Coche.prototype.modelo = "Astra";
Coche.prototype.anyo = 2002;
Coche.prototype.returnMarca = function(){
        alert(this.marca);
    };
}
var coche1 = new Coche();
var coche2 = new Coche();

Al invocar “new Coche” todas las propiedades del prototipo se asignan de inmediato al objeto, o sea que todas las instancias de Coche contienen punteros a la misma función mostrarMarca(). Además, el problema semántico ya no existe, porque como veis parece que todo pertenece al mismo objeto.

Hasta aquí todo bien, se acababan de solucionar los problemas de los anteriores paradigmas, pero… queda algo importante, ¿y los argumentos? y no solo eso, ¿qué sucede cuando una de las propiedades apunta a un objeto y no a una función?

Y de aquí, pasamos a combinar lo mejor de los anteriores paradigmas

Paradigma Híbrido Constructores/Prototipos

function Coche(marca, modelo, anyo){
    this.marca = marca;
    this.modelo = modelo;
    this.anyo = anyo;
    this.conductores = new Array("ALO","VET");
}

Coche.prototype.mostrarMarca = function(){
    alert(this.marca);
}

var coche1 = new Coche("Seat", "Ibiza", 2012);
var coche2 = new Coche("Opel", "Astra", 2002);

coche2.conductores.push("HAM");

alert(coche1.conductores); // ni rastro de HAM
alert(coche2.conductores); // aquí sí está HAM

Solo se crea una instancia de mostrarMarca() y además las matrices son independientes en cada objeto. Podríamos decir que “prueba superada”.

Paradigma de Prototipos Dinámicos

function Coche(marca, modelo, anyo){
    this.marca = marca;
    this.modelo = modelo;
    this.anyo = anyo;
    this.conductores = new Array("ALO","VET");
    if(typeof Coche._initialized == "undefined"){
        Coche.prototype.mostrarMarca = function(){
            alert(this.marca);
        };
        Coche._inizialized = true;
    }
}

Si el valor es undefined el constructor prosigue y lo marca como inizializado. Los métodos solo se asignan una vez.

Por cierto, si usáis el paradigma de prototipos, hay una forma más clara de escribirlo:

function Coche(){}
Coche.prototype = {
    marca: "Opel",
    modelo: "Astra",
    anyo: 2002,
    returnMarca: function(){
        alert(this.marca);
    }
};

Javascript nos ofrece tantas formas de llegar al mismo sitio, que… o lo amas, o lo odias.

El el próximo post hablaremos de las formas de definir una función, y entenderéis mejor la frase “Javascript nos ofrece tantas formas de llegar al mismo sitio”.

Una Respuesta a Javascript: Patrones de diseño en la creación de objetos

  1. Oscar Bravo
    says: 7 agosto, 2013 a las 22:29

    Excelente aporte muchas gracias.. felicidades por su trabajo me parece muy bueno..ya habia leido un poco sobre este tema aki esta el link por si alguien mas le interesa leer un poco mas sobre el tema..
    http://quechuletas.blogspot.mx/2013/07/patrones-en-javascript-prototype-pattern.html

    Responder

Deja un comentario

Una web debe ser...

Una web
debe ser

Usable

Un usuario aprende cada día. Navega y utiliza servicios web acostumbrándose a tener algunos elementos en determinado lugar y a utilizarlos de cierta manera. Una aplicación es usable si antes de hacer una determinada acción se puede predecir lo que sucederá.

Universal

El punto de mayor incidencia en la universalidad es que la aplicación sea multidispositivo. Poder visualizar desde cualquier dispositivo, lugar, y momento. Y además, disfrutar de una experiencia de usuario plena.

Encontrable

Hablamos de un conjunto de normas, pautas o guías por las que el usuario llega a la aplicación. Debe encontrar la aplicación, pero puede llegar mediante buscadores (SEO), también con recomendaciones, lecturas en medios, desde redes sociales (SMO), y otros métodos (SEM, etc)

Veloz

Como dijo David Cheriton: "Si es rápido y feo, lo utilizarán y te maldecirán, y si es lento, no lo utilizarán". Si una web es rápida repercute en menos gasto mensual, más satisfacción del usuario, y mayor posibilidad de conversión por parte del mismo.

Útil

Un sitio web tiene que ser útil en vistas al usuario para el que está concebido. Hay que entender la necesidad del usuario y poder ofrecer lo que busca. Contenidos, traducciones, herramientas, comparativas, utilidades, etcétera...

Cerrar