martes, 7 de septiembre de 2010

Patron Factory

Hoy es un día de alegría para mí. He puesto en código de producción mi segundo patrón aprendido y aprehendido (como decía mi profesora de inglés).

Tengamos una clase que representa a un número tal cual así:
public class Numero
{
    private int _cifra;
    public int cifra
    {
        get { return _cifra; }
        set{ _cifra = value; }
    }
}
Esta clase lo único que hace es almacenar una cifra numérica en una propiedad pública llamada cifra. Y tiene un constructor (absolutamente prescindible) vacio. Osea que no hace más que construir una instancia de nuestro número.

Ahora voy a llamar a otra clase, muy simple, llamada GestionDeNumeros que tiene un solo método que recupera un número y hace “algo” con él. Osea que de forma tradicional instancio la clase número e introduzco un valor en su propiedad cifra.
public class GestionNumeros
{
    public void RecuperaNumero()
    {
        NumeroobjetoNumero = newNumero();
        int resultado = objetoNumero.cifra + 1;
    }
}
Pero, si quiero delimitar de forma más estricta el número que me quiero traer tengo la opción de hacer un nuevo constructor que tenga como parámetro de entrada la cifra que quiero obtener,
    public class Numero
  
{
        private int _cifra;
        public int cifra
        {
            get { return _cifra; }
            set{ _cifra = value; }
        }

        public Numero(int pCifra)
        { _cifra = pCifra; }

    }

    public class GestionNumeros
  
{
        public void RecuperaNumero()
        {
            NumeroobjNumero = newNumero(5);
            int suma = objNumero.cifra + 1;
        }
    }
}
Pero ¿si quiero recuperar un número que sea distinto al que le quiero pasar? o si quiero un numero que esté entre otros dos números? o que sea el primer número par mayor que el número que le paso por parámetro? o que sea el número que le paso por parámetro multiplicado por si mismo?

Como ves si lo quisiera hacer por constructores sobrecargados me acababa de meter en un berenjenal de narices. Pero gracias al patrón Factory y a quien lo halla descubierto y explicado, es tan simple como el crear métodos estáticos de la clase que realicen la construcción y que  me devuelvan la instancia. Vamos a hacer el último requisito, para que se vea lo sencillo que es y la potencialidad, construyendo el método estático que me va a construir el objeto número que deseamos,
public class Numero
{
    private int _cifra;
    public int cifra
    {
        get { return _cifra; }
        set{ _cifra = value; }
    }

    public Numero()
    { }

    public static Numero CreaNumeroMultiplicadoPorSiMismo(int numero)
    {
        Numero objetoNumero = new Numero();
        objetoNumero.cifra = numero * numero;
        return objetoNumero;
    }

}
Y ahora lo vamos a invocar, que es donde está la magia,
public class GestionNumeros
{
public void RecuperaNumero()
{ 
Numero resultado = Numero.CreaNumeroMultiplicadoPorSiMismo(5);
}
}


Teniendo en cuenta que con este patrón le puedo pasar cualquier tipo de información al constructor, es de indudable potencia y utilidad una vez que el escurridizo concepto se entiende.


P.D. Siguiente objetivo: Utilizar una interface…

Actualización 09/09/2010 Muy buen documento sobre patrones de fabrica

5 comentarios:

Gabriel Falcone dijo...

Hola Juan,

Te felicito por tu blog, ademas leo tus posts en las lista agiles.
Desde mi punto de vista aquí no estás usas el patron Factory Method tal como es descripto en el libro de Gamma.
De todas formas es una buena idea lo que has hecho. El problema que existe con los constructores es que todos tienen el mismo nombre (el nombre de la clase, por supuesto) y esto hace que no nos sea posible ser mas expresivos en cuanto al comportamiento que cada constructor tiene.

Saludos desde Argentina,
Gabriel.

Juan Quijano dijo...

Siente libre de corregirme. Escribe un ejemplo de cómo sería la implementación corrécta, please.

Gonzalo dijo...
Este comentario ha sido eliminado por el autor.
Gonzalo dijo...

Un detalle: No tengo ni idea de C# pero ¿no debería ser

set{ _cifra = value; }

en lugar de

set{ value = _cifra; }

?

Juan Quijano dijo...

Tienes toda la razón... que vergüenza!!

Ya está corregido.